simploxide_api_types/
client_api.rs

1use crate::{commands::*, responses::*, utils::CommandSyntax, *};
2use std::future::Future;
3use std::sync::Arc;
4
5pub trait ClientApiError: From<BadResponseError> + std::error::Error {
6    /// If current error is a bad response error return a mut reference to it!
7    ///
8    /// Required for [`AllowUndocumentedResponses`] impl.
9    fn bad_response_mut(&mut self) -> Option<&mut BadResponseError>;
10}
11
12pub trait ClientApi: Sync {
13    type Error: ClientApiError;
14
15    fn send_raw(
16        &self,
17        command: String,
18    ) -> impl Future<Output = Result<JsonObject, Self::Error>> + Send;
19
20    /// ### Address commands
21    ///
22    /// Bots can use these commands to automatically check and create address when initialized
23    ///
24    /// ----
25    ///
26    /// Create bot address.
27    ///
28    /// *Network usage*: interactive.
29    ///
30    /// *Syntax:*
31    ///
32    /// ```
33    /// /_address <userId>
34    /// ```
35    fn api_create_my_address(
36        &self,
37        user_id: i64,
38    ) -> impl Future<Output = Result<Arc<UserContactLinkCreatedResponse>, Self::Error>> + Send {
39        async move {
40            let command = ApiCreateMyAddress { user_id };
41            let json = self.send_raw(command.interpret()).await?;
42            // Safe to unwrap because unrecognized JSON goes to undocumented variant
43            let response = serde_json::from_value(json).unwrap();
44            match response {
45                ApiCreateMyAddressResponse::UserContactLinkCreated(resp) => Ok(Arc::new(resp)),
46                ApiCreateMyAddressResponse::ChatCmdError(resp) => {
47                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
48                }
49                ApiCreateMyAddressResponse::Undocumented(resp) => {
50                    Err(BadResponseError::Undocumented(resp).into())
51                }
52            }
53        }
54    }
55
56    /// ### Address commands
57    ///
58    /// Bots can use these commands to automatically check and create address when initialized
59    ///
60    /// ----
61    ///
62    /// Delete bot address.
63    ///
64    /// *Network usage*: background.
65    ///
66    /// *Syntax:*
67    ///
68    /// ```
69    /// /_delete_address <userId>
70    /// ```
71    fn api_delete_my_address(
72        &self,
73        user_id: i64,
74    ) -> impl Future<Output = Result<Arc<User>, Self::Error>> + Send {
75        async move {
76            let command = ApiDeleteMyAddress { user_id };
77            let json = self.send_raw(command.interpret()).await?;
78            // Safe to unwrap because unrecognized JSON goes to undocumented variant
79            let response = serde_json::from_value(json).unwrap();
80            match response {
81                ApiDeleteMyAddressResponse::UserContactLinkDeleted(resp) => Ok(Arc::new(resp.user)),
82                ApiDeleteMyAddressResponse::ChatCmdError(resp) => {
83                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
84                }
85                ApiDeleteMyAddressResponse::Undocumented(resp) => {
86                    Err(BadResponseError::Undocumented(resp).into())
87                }
88            }
89        }
90    }
91
92    /// ### Address commands
93    ///
94    /// Bots can use these commands to automatically check and create address when initialized
95    ///
96    /// ----
97    ///
98    /// Get bot address and settings.
99    ///
100    /// *Network usage*: no.
101    ///
102    /// *Syntax:*
103    ///
104    /// ```
105    /// /_show_address <userId>
106    /// ```
107    fn api_show_my_address(
108        &self,
109        user_id: i64,
110    ) -> impl Future<Output = Result<Arc<UserContactLinkResponse>, Self::Error>> + Send {
111        async move {
112            let command = ApiShowMyAddress { user_id };
113            let json = self.send_raw(command.interpret()).await?;
114            // Safe to unwrap because unrecognized JSON goes to undocumented variant
115            let response = serde_json::from_value(json).unwrap();
116            match response {
117                ApiShowMyAddressResponse::UserContactLink(resp) => Ok(Arc::new(resp)),
118                ApiShowMyAddressResponse::ChatCmdError(resp) => {
119                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
120                }
121                ApiShowMyAddressResponse::Undocumented(resp) => {
122                    Err(BadResponseError::Undocumented(resp).into())
123                }
124            }
125        }
126    }
127
128    /// ### Address commands
129    ///
130    /// Bots can use these commands to automatically check and create address when initialized
131    ///
132    /// ----
133    ///
134    /// Add address to bot profile.
135    ///
136    /// *Network usage*: interactive.
137    ///
138    /// *Syntax:*
139    ///
140    /// ```
141    /// /_profile_address <userId> on|off
142    /// ```
143    fn api_set_profile_address(
144        &self,
145        command: ApiSetProfileAddress,
146    ) -> impl Future<Output = Result<Arc<UserProfileUpdatedResponse>, Self::Error>> + Send {
147        async move {
148            let json = self.send_raw(command.interpret()).await?;
149            // Safe to unwrap because unrecognized JSON goes to undocumented variant
150            let response = serde_json::from_value(json).unwrap();
151            match response {
152                ApiSetProfileAddressResponse::UserProfileUpdated(resp) => Ok(Arc::new(resp)),
153                ApiSetProfileAddressResponse::ChatCmdError(resp) => {
154                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
155                }
156                ApiSetProfileAddressResponse::Undocumented(resp) => {
157                    Err(BadResponseError::Undocumented(resp).into())
158                }
159            }
160        }
161    }
162
163    /// ### Address commands
164    ///
165    /// Bots can use these commands to automatically check and create address when initialized
166    ///
167    /// ----
168    ///
169    /// Set bot address settings.
170    ///
171    /// *Network usage*: interactive.
172    ///
173    /// *Syntax:*
174    ///
175    /// ```
176    /// /_address_settings <userId> <json(settings)>
177    /// ```
178    fn api_set_address_settings(
179        &self,
180        user_id: i64,
181        settings: AddressSettings,
182    ) -> impl Future<Output = Result<Arc<UserContactLinkUpdatedResponse>, Self::Error>> + Send {
183        async move {
184            let command = ApiSetAddressSettings { user_id, settings };
185            let json = self.send_raw(command.interpret()).await?;
186            // Safe to unwrap because unrecognized JSON goes to undocumented variant
187            let response = serde_json::from_value(json).unwrap();
188            match response {
189                ApiSetAddressSettingsResponse::UserContactLinkUpdated(resp) => Ok(Arc::new(resp)),
190                ApiSetAddressSettingsResponse::ChatCmdError(resp) => {
191                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
192                }
193                ApiSetAddressSettingsResponse::Undocumented(resp) => {
194                    Err(BadResponseError::Undocumented(resp).into())
195                }
196            }
197        }
198    }
199
200    /// ### Message commands
201    ///
202    /// Commands to send, update, delete, moderate messages and set message reactions
203    ///
204    /// ----
205    ///
206    /// Send messages.
207    ///
208    /// *Network usage*: background.
209    ///
210    /// *Syntax:*
211    ///
212    /// ```
213    /// /_send <str(sendRef)>[ live=on][ ttl=<ttl>] json <json(composedMessages)>
214    /// ```
215    fn api_send_messages(
216        &self,
217        command: ApiSendMessages,
218    ) -> impl Future<Output = Result<Arc<NewChatItemsResponse>, Self::Error>> + Send {
219        async move {
220            let json = self.send_raw(command.interpret()).await?;
221            // Safe to unwrap because unrecognized JSON goes to undocumented variant
222            let response = serde_json::from_value(json).unwrap();
223            match response {
224                ApiSendMessagesResponse::NewChatItems(resp) => Ok(Arc::new(resp)),
225                ApiSendMessagesResponse::ChatCmdError(resp) => {
226                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
227                }
228                ApiSendMessagesResponse::Undocumented(resp) => {
229                    Err(BadResponseError::Undocumented(resp).into())
230                }
231            }
232        }
233    }
234
235    /// ### Message commands
236    ///
237    /// Commands to send, update, delete, moderate messages and set message reactions
238    ///
239    /// ----
240    ///
241    /// Update message.
242    ///
243    /// *Network usage*: background.
244    ///
245    /// *Syntax:*
246    ///
247    /// ```
248    /// /_update item <str(chatRef)> <chatItemId>[ live=on] json <json(updatedMessage)>
249    /// ```
250    fn api_update_chat_item(
251        &self,
252        command: ApiUpdateChatItem,
253    ) -> impl Future<Output = Result<ApiUpdateChatItemResponses, Self::Error>> + Send {
254        async move {
255            let json = self.send_raw(command.interpret()).await?;
256            // Safe to unwrap because unrecognized JSON goes to undocumented variant
257            let response = serde_json::from_value(json).unwrap();
258            match response {
259                ApiUpdateChatItemResponse::ChatItemUpdated(resp) => {
260                    Ok(ApiUpdateChatItemResponses::ChatItemUpdated(Arc::new(resp)))
261                }
262                ApiUpdateChatItemResponse::ChatItemNotChanged(resp) => Ok(
263                    ApiUpdateChatItemResponses::ChatItemNotChanged(Arc::new(resp)),
264                ),
265                ApiUpdateChatItemResponse::ChatCmdError(resp) => {
266                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
267                }
268                ApiUpdateChatItemResponse::Undocumented(resp) => {
269                    Err(BadResponseError::Undocumented(resp).into())
270                }
271            }
272        }
273    }
274
275    /// ### Message commands
276    ///
277    /// Commands to send, update, delete, moderate messages and set message reactions
278    ///
279    /// ----
280    ///
281    /// Delete message.
282    ///
283    /// *Network usage*: background.
284    ///
285    /// *Syntax:*
286    ///
287    /// ```
288    /// /_delete item <str(chatRef)> <chatItemIds[0]>[,<chatItemIds[1]>...] broadcast|internal|internalMark
289    /// ```
290    fn api_delete_chat_item(
291        &self,
292        chat_ref: ChatRef,
293        chat_item_ids: Vec<i64>,
294        delete_mode: CIDeleteMode,
295    ) -> impl Future<Output = Result<Arc<ChatItemsDeletedResponse>, Self::Error>> + Send {
296        async move {
297            let command = ApiDeleteChatItem {
298                chat_ref,
299                chat_item_ids,
300                delete_mode,
301            };
302            let json = self.send_raw(command.interpret()).await?;
303            // Safe to unwrap because unrecognized JSON goes to undocumented variant
304            let response = serde_json::from_value(json).unwrap();
305            match response {
306                ApiDeleteChatItemResponse::ChatItemsDeleted(resp) => Ok(Arc::new(resp)),
307                ApiDeleteChatItemResponse::ChatCmdError(resp) => {
308                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
309                }
310                ApiDeleteChatItemResponse::Undocumented(resp) => {
311                    Err(BadResponseError::Undocumented(resp).into())
312                }
313            }
314        }
315    }
316
317    /// ### Message commands
318    ///
319    /// Commands to send, update, delete, moderate messages and set message reactions
320    ///
321    /// ----
322    ///
323    /// Moderate message. Requires Moderator role (and higher than message author's).
324    ///
325    /// *Network usage*: background.
326    ///
327    /// *Syntax:*
328    ///
329    /// ```
330    /// /_delete member item #<groupId> <chatItemIds[0]>[,<chatItemIds[1]>...]
331    /// ```
332    fn api_delete_member_chat_item(
333        &self,
334        group_id: i64,
335        chat_item_ids: Vec<i64>,
336    ) -> impl Future<Output = Result<Arc<ChatItemsDeletedResponse>, Self::Error>> + Send {
337        async move {
338            let command = ApiDeleteMemberChatItem {
339                group_id,
340                chat_item_ids,
341            };
342            let json = self.send_raw(command.interpret()).await?;
343            // Safe to unwrap because unrecognized JSON goes to undocumented variant
344            let response = serde_json::from_value(json).unwrap();
345            match response {
346                ApiDeleteMemberChatItemResponse::ChatItemsDeleted(resp) => Ok(Arc::new(resp)),
347                ApiDeleteMemberChatItemResponse::ChatCmdError(resp) => {
348                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
349                }
350                ApiDeleteMemberChatItemResponse::Undocumented(resp) => {
351                    Err(BadResponseError::Undocumented(resp).into())
352                }
353            }
354        }
355    }
356
357    /// ### Message commands
358    ///
359    /// Commands to send, update, delete, moderate messages and set message reactions
360    ///
361    /// ----
362    ///
363    /// Add/remove message reaction.
364    ///
365    /// *Network usage*: background.
366    ///
367    /// *Syntax:*
368    ///
369    /// ```
370    /// /_reaction <str(chatRef)> <chatItemId> on|off <json(reaction)>
371    /// ```
372    fn api_chat_item_reaction(
373        &self,
374        command: ApiChatItemReaction,
375    ) -> impl Future<Output = Result<Arc<ChatItemReactionResponse>, Self::Error>> + Send {
376        async move {
377            let json = self.send_raw(command.interpret()).await?;
378            // Safe to unwrap because unrecognized JSON goes to undocumented variant
379            let response = serde_json::from_value(json).unwrap();
380            match response {
381                ApiChatItemReactionResponse::ChatItemReaction(resp) => Ok(Arc::new(resp)),
382                ApiChatItemReactionResponse::ChatCmdError(resp) => {
383                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
384                }
385                ApiChatItemReactionResponse::Undocumented(resp) => {
386                    Err(BadResponseError::Undocumented(resp).into())
387                }
388            }
389        }
390    }
391
392    /// ### File commands
393    ///
394    /// Commands to receive and to cancel files. Files are sent as part of the message, there are no separate commands to send files.
395    ///
396    /// ----
397    ///
398    /// Receive file.
399    ///
400    /// *Network usage*: no.
401    ///
402    /// *Syntax:*
403    ///
404    /// ```
405    /// /freceive <fileId>[ approved_relays=on][ encrypt=on|off][ inline=on|off][ <filePath>]
406    /// ```
407    fn receive_file(
408        &self,
409        command: ReceiveFile,
410    ) -> impl Future<Output = Result<ReceiveFileResponses, Self::Error>> + Send {
411        async move {
412            let json = self.send_raw(command.interpret()).await?;
413            // Safe to unwrap because unrecognized JSON goes to undocumented variant
414            let response = serde_json::from_value(json).unwrap();
415            match response {
416                ReceiveFileResponse::RcvFileAccepted(resp) => {
417                    Ok(ReceiveFileResponses::RcvFileAccepted(Arc::new(resp)))
418                }
419                ReceiveFileResponse::RcvFileAcceptedSndCancelled(resp) => Ok(
420                    ReceiveFileResponses::RcvFileAcceptedSndCancelled(Arc::new(resp)),
421                ),
422                ReceiveFileResponse::ChatCmdError(resp) => {
423                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
424                }
425                ReceiveFileResponse::Undocumented(resp) => {
426                    Err(BadResponseError::Undocumented(resp).into())
427                }
428            }
429        }
430    }
431
432    /// ### File commands
433    ///
434    /// Commands to receive and to cancel files. Files are sent as part of the message, there are no separate commands to send files.
435    ///
436    /// ----
437    ///
438    /// Cancel file.
439    ///
440    /// *Network usage*: background.
441    ///
442    /// *Syntax:*
443    ///
444    /// ```
445    /// /fcancel <fileId>
446    /// ```
447    fn cancel_file(
448        &self,
449        file_id: i64,
450    ) -> impl Future<Output = Result<CancelFileResponses, Self::Error>> + Send {
451        async move {
452            let command = CancelFile { file_id };
453            let json = self.send_raw(command.interpret()).await?;
454            // Safe to unwrap because unrecognized JSON goes to undocumented variant
455            let response = serde_json::from_value(json).unwrap();
456            match response {
457                CancelFileResponse::SndFileCancelled(resp) => {
458                    Ok(CancelFileResponses::SndFileCancelled(Arc::new(resp)))
459                }
460                CancelFileResponse::RcvFileCancelled(resp) => {
461                    Ok(CancelFileResponses::RcvFileCancelled(Arc::new(resp)))
462                }
463                CancelFileResponse::ChatCmdError(resp) => {
464                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
465                }
466                CancelFileResponse::Undocumented(resp) => {
467                    Err(BadResponseError::Undocumented(resp).into())
468                }
469            }
470        }
471    }
472
473    /// ### Group commands
474    ///
475    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
476    ///
477    /// ----
478    ///
479    /// Add contact to group. Requires bot to have Admin role.
480    ///
481    /// *Network usage*: interactive.
482    ///
483    /// *Syntax:*
484    ///
485    /// ```
486    /// /_add #<groupId> <contactId> observer|author|member|moderator|admin|owner
487    /// ```
488    fn api_add_member(
489        &self,
490        group_id: i64,
491        contact_id: i64,
492        member_role: GroupMemberRole,
493    ) -> impl Future<Output = Result<Arc<SentGroupInvitationResponse>, Self::Error>> + Send {
494        async move {
495            let command = ApiAddMember {
496                group_id,
497                contact_id,
498                member_role,
499            };
500            let json = self.send_raw(command.interpret()).await?;
501            // Safe to unwrap because unrecognized JSON goes to undocumented variant
502            let response = serde_json::from_value(json).unwrap();
503            match response {
504                ApiAddMemberResponse::SentGroupInvitation(resp) => Ok(Arc::new(resp)),
505                ApiAddMemberResponse::ChatCmdError(resp) => {
506                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
507                }
508                ApiAddMemberResponse::Undocumented(resp) => {
509                    Err(BadResponseError::Undocumented(resp).into())
510                }
511            }
512        }
513    }
514
515    /// ### Group commands
516    ///
517    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
518    ///
519    /// ----
520    ///
521    /// Join group.
522    ///
523    /// *Network usage*: interactive.
524    ///
525    /// *Syntax:*
526    ///
527    /// ```
528    /// /_join #<groupId>
529    /// ```
530    fn api_join_group(
531        &self,
532        group_id: i64,
533    ) -> impl Future<Output = Result<Arc<UserAcceptedGroupSentResponse>, Self::Error>> + Send {
534        async move {
535            let command = ApiJoinGroup { group_id };
536            let json = self.send_raw(command.interpret()).await?;
537            // Safe to unwrap because unrecognized JSON goes to undocumented variant
538            let response = serde_json::from_value(json).unwrap();
539            match response {
540                ApiJoinGroupResponse::UserAcceptedGroupSent(resp) => Ok(Arc::new(resp)),
541                ApiJoinGroupResponse::ChatCmdError(resp) => {
542                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
543                }
544                ApiJoinGroupResponse::Undocumented(resp) => {
545                    Err(BadResponseError::Undocumented(resp).into())
546                }
547            }
548        }
549    }
550
551    /// ### Group commands
552    ///
553    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
554    ///
555    /// ----
556    ///
557    /// Accept group member. Requires Admin role.
558    ///
559    /// *Network usage*: background.
560    ///
561    /// *Syntax:*
562    ///
563    /// ```
564    /// /_accept member #<groupId> <groupMemberId> observer|author|member|moderator|admin|owner
565    /// ```
566    fn api_accept_member(
567        &self,
568        group_id: i64,
569        group_member_id: i64,
570        member_role: GroupMemberRole,
571    ) -> impl Future<Output = Result<Arc<MemberAcceptedResponse>, Self::Error>> + Send {
572        async move {
573            let command = ApiAcceptMember {
574                group_id,
575                group_member_id,
576                member_role,
577            };
578            let json = self.send_raw(command.interpret()).await?;
579            // Safe to unwrap because unrecognized JSON goes to undocumented variant
580            let response = serde_json::from_value(json).unwrap();
581            match response {
582                ApiAcceptMemberResponse::MemberAccepted(resp) => Ok(Arc::new(resp)),
583                ApiAcceptMemberResponse::ChatCmdError(resp) => {
584                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
585                }
586                ApiAcceptMemberResponse::Undocumented(resp) => {
587                    Err(BadResponseError::Undocumented(resp).into())
588                }
589            }
590        }
591    }
592
593    /// ### Group commands
594    ///
595    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
596    ///
597    /// ----
598    ///
599    /// Set members role. Requires Admin role.
600    ///
601    /// *Network usage*: background.
602    ///
603    /// *Syntax:*
604    ///
605    /// ```
606    /// /_member role #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...] observer|author|member|moderator|admin|owner
607    /// ```
608    fn api_members_role(
609        &self,
610        group_id: i64,
611        group_member_ids: Vec<i64>,
612        member_role: GroupMemberRole,
613    ) -> impl Future<Output = Result<Arc<MembersRoleUserResponse>, Self::Error>> + Send {
614        async move {
615            let command = ApiMembersRole {
616                group_id,
617                group_member_ids,
618                member_role,
619            };
620            let json = self.send_raw(command.interpret()).await?;
621            // Safe to unwrap because unrecognized JSON goes to undocumented variant
622            let response = serde_json::from_value(json).unwrap();
623            match response {
624                ApiMembersRoleResponse::MembersRoleUser(resp) => Ok(Arc::new(resp)),
625                ApiMembersRoleResponse::ChatCmdError(resp) => {
626                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
627                }
628                ApiMembersRoleResponse::Undocumented(resp) => {
629                    Err(BadResponseError::Undocumented(resp).into())
630                }
631            }
632        }
633    }
634
635    /// ### Group commands
636    ///
637    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
638    ///
639    /// ----
640    ///
641    /// Block members. Requires Moderator role.
642    ///
643    /// *Network usage*: background.
644    ///
645    /// *Syntax:*
646    ///
647    /// ```
648    /// /_block #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...] blocked=on|off
649    /// ```
650    fn api_block_members_for_all(
651        &self,
652        command: ApiBlockMembersForAll,
653    ) -> impl Future<Output = Result<Arc<MembersBlockedForAllUserResponse>, Self::Error>> + Send
654    {
655        async move {
656            let json = self.send_raw(command.interpret()).await?;
657            // Safe to unwrap because unrecognized JSON goes to undocumented variant
658            let response = serde_json::from_value(json).unwrap();
659            match response {
660                ApiBlockMembersForAllResponse::MembersBlockedForAllUser(resp) => Ok(Arc::new(resp)),
661                ApiBlockMembersForAllResponse::ChatCmdError(resp) => {
662                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
663                }
664                ApiBlockMembersForAllResponse::Undocumented(resp) => {
665                    Err(BadResponseError::Undocumented(resp).into())
666                }
667            }
668        }
669    }
670
671    /// ### Group commands
672    ///
673    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
674    ///
675    /// ----
676    ///
677    /// Remove members. Requires Admin role.
678    ///
679    /// *Network usage*: background.
680    ///
681    /// *Syntax:*
682    ///
683    /// ```
684    /// /_remove #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...][ messages=on]
685    /// ```
686    fn api_remove_members(
687        &self,
688        command: ApiRemoveMembers,
689    ) -> impl Future<Output = Result<Arc<UserDeletedMembersResponse>, Self::Error>> + Send {
690        async move {
691            let json = self.send_raw(command.interpret()).await?;
692            // Safe to unwrap because unrecognized JSON goes to undocumented variant
693            let response = serde_json::from_value(json).unwrap();
694            match response {
695                ApiRemoveMembersResponse::UserDeletedMembers(resp) => Ok(Arc::new(resp)),
696                ApiRemoveMembersResponse::ChatCmdError(resp) => {
697                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
698                }
699                ApiRemoveMembersResponse::Undocumented(resp) => {
700                    Err(BadResponseError::Undocumented(resp).into())
701                }
702            }
703        }
704    }
705
706    /// ### Group commands
707    ///
708    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
709    ///
710    /// ----
711    ///
712    /// Leave group.
713    ///
714    /// *Network usage*: background.
715    ///
716    /// *Syntax:*
717    ///
718    /// ```
719    /// /_leave #<groupId>
720    /// ```
721    fn api_leave_group(
722        &self,
723        group_id: i64,
724    ) -> impl Future<Output = Result<Arc<LeftMemberUserResponse>, Self::Error>> + Send {
725        async move {
726            let command = ApiLeaveGroup { group_id };
727            let json = self.send_raw(command.interpret()).await?;
728            // Safe to unwrap because unrecognized JSON goes to undocumented variant
729            let response = serde_json::from_value(json).unwrap();
730            match response {
731                ApiLeaveGroupResponse::LeftMemberUser(resp) => Ok(Arc::new(resp)),
732                ApiLeaveGroupResponse::ChatCmdError(resp) => {
733                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
734                }
735                ApiLeaveGroupResponse::Undocumented(resp) => {
736                    Err(BadResponseError::Undocumented(resp).into())
737                }
738            }
739        }
740    }
741
742    /// ### Group commands
743    ///
744    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
745    ///
746    /// ----
747    ///
748    /// Get group members.
749    ///
750    /// *Network usage*: no.
751    ///
752    /// *Syntax:*
753    ///
754    /// ```
755    /// /_members #<groupId>
756    /// ```
757    fn api_list_members(
758        &self,
759        group_id: i64,
760    ) -> impl Future<Output = Result<Arc<GroupMembersResponse>, Self::Error>> + Send {
761        async move {
762            let command = ApiListMembers { group_id };
763            let json = self.send_raw(command.interpret()).await?;
764            // Safe to unwrap because unrecognized JSON goes to undocumented variant
765            let response = serde_json::from_value(json).unwrap();
766            match response {
767                ApiListMembersResponse::GroupMembers(resp) => Ok(Arc::new(resp)),
768                ApiListMembersResponse::ChatCmdError(resp) => {
769                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
770                }
771                ApiListMembersResponse::Undocumented(resp) => {
772                    Err(BadResponseError::Undocumented(resp).into())
773                }
774            }
775        }
776    }
777
778    /// ### Group commands
779    ///
780    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
781    ///
782    /// ----
783    ///
784    /// Create group.
785    ///
786    /// *Network usage*: no.
787    ///
788    /// *Syntax:*
789    ///
790    /// ```
791    /// /_group <userId>[ incognito=on] <json(groupProfile)>
792    /// ```
793    fn api_new_group(
794        &self,
795        command: ApiNewGroup,
796    ) -> impl Future<Output = Result<Arc<GroupCreatedResponse>, Self::Error>> + Send {
797        async move {
798            let json = self.send_raw(command.interpret()).await?;
799            // Safe to unwrap because unrecognized JSON goes to undocumented variant
800            let response = serde_json::from_value(json).unwrap();
801            match response {
802                ApiNewGroupResponse::GroupCreated(resp) => Ok(Arc::new(resp)),
803                ApiNewGroupResponse::ChatCmdError(resp) => {
804                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
805                }
806                ApiNewGroupResponse::Undocumented(resp) => {
807                    Err(BadResponseError::Undocumented(resp).into())
808                }
809            }
810        }
811    }
812
813    /// ### Group commands
814    ///
815    /// Commands to manage and moderate groups. These commands can be used with business chats as well - they are groups. E.g., a common scenario would be to add human agents to business chat with the customer who connected via business address.
816    ///
817    /// ----
818    ///
819    /// Update group profile.
820    ///
821    /// *Network usage*: background.
822    ///
823    /// *Syntax:*
824    ///
825    /// ```
826    /// /_group_profile #<groupId> <json(groupProfile)>
827    /// ```
828    fn api_update_group_profile(
829        &self,
830        group_id: i64,
831        group_profile: GroupProfile,
832    ) -> impl Future<Output = Result<Arc<GroupUpdatedResponse>, Self::Error>> + Send {
833        async move {
834            let command = ApiUpdateGroupProfile {
835                group_id,
836                group_profile,
837            };
838            let json = self.send_raw(command.interpret()).await?;
839            // Safe to unwrap because unrecognized JSON goes to undocumented variant
840            let response = serde_json::from_value(json).unwrap();
841            match response {
842                ApiUpdateGroupProfileResponse::GroupUpdated(resp) => Ok(Arc::new(resp)),
843                ApiUpdateGroupProfileResponse::ChatCmdError(resp) => {
844                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
845                }
846                ApiUpdateGroupProfileResponse::Undocumented(resp) => {
847                    Err(BadResponseError::Undocumented(resp).into())
848                }
849            }
850        }
851    }
852
853    /// ### Group link commands
854    ///
855    /// These commands can be used by bots that manage multiple public groups
856    ///
857    /// ----
858    ///
859    /// Create group link.
860    ///
861    /// *Network usage*: interactive.
862    ///
863    /// *Syntax:*
864    ///
865    /// ```
866    /// /_create link #<groupId> observer|author|member|moderator|admin|owner
867    /// ```
868    fn api_create_group_link(
869        &self,
870        group_id: i64,
871        member_role: GroupMemberRole,
872    ) -> impl Future<Output = Result<Arc<GroupLinkCreatedResponse>, Self::Error>> + Send {
873        async move {
874            let command = ApiCreateGroupLink {
875                group_id,
876                member_role,
877            };
878            let json = self.send_raw(command.interpret()).await?;
879            // Safe to unwrap because unrecognized JSON goes to undocumented variant
880            let response = serde_json::from_value(json).unwrap();
881            match response {
882                ApiCreateGroupLinkResponse::GroupLinkCreated(resp) => Ok(Arc::new(resp)),
883                ApiCreateGroupLinkResponse::ChatCmdError(resp) => {
884                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
885                }
886                ApiCreateGroupLinkResponse::Undocumented(resp) => {
887                    Err(BadResponseError::Undocumented(resp).into())
888                }
889            }
890        }
891    }
892
893    /// ### Group link commands
894    ///
895    /// These commands can be used by bots that manage multiple public groups
896    ///
897    /// ----
898    ///
899    /// Set member role for group link.
900    ///
901    /// *Network usage*: no.
902    ///
903    /// *Syntax:*
904    ///
905    /// ```
906    /// /_set link role #<groupId> observer|author|member|moderator|admin|owner
907    /// ```
908    fn api_group_link_member_role(
909        &self,
910        group_id: i64,
911        member_role: GroupMemberRole,
912    ) -> impl Future<Output = Result<Arc<GroupLinkResponse>, Self::Error>> + Send {
913        async move {
914            let command = ApiGroupLinkMemberRole {
915                group_id,
916                member_role,
917            };
918            let json = self.send_raw(command.interpret()).await?;
919            // Safe to unwrap because unrecognized JSON goes to undocumented variant
920            let response = serde_json::from_value(json).unwrap();
921            match response {
922                ApiGroupLinkMemberRoleResponse::GroupLink(resp) => Ok(Arc::new(resp)),
923                ApiGroupLinkMemberRoleResponse::ChatCmdError(resp) => {
924                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
925                }
926                ApiGroupLinkMemberRoleResponse::Undocumented(resp) => {
927                    Err(BadResponseError::Undocumented(resp).into())
928                }
929            }
930        }
931    }
932
933    /// ### Group link commands
934    ///
935    /// These commands can be used by bots that manage multiple public groups
936    ///
937    /// ----
938    ///
939    /// Delete group link.
940    ///
941    /// *Network usage*: background.
942    ///
943    /// *Syntax:*
944    ///
945    /// ```
946    /// /_delete link #<groupId>
947    /// ```
948    fn api_delete_group_link(
949        &self,
950        group_id: i64,
951    ) -> impl Future<Output = Result<Arc<GroupLinkDeletedResponse>, Self::Error>> + Send {
952        async move {
953            let command = ApiDeleteGroupLink { group_id };
954            let json = self.send_raw(command.interpret()).await?;
955            // Safe to unwrap because unrecognized JSON goes to undocumented variant
956            let response = serde_json::from_value(json).unwrap();
957            match response {
958                ApiDeleteGroupLinkResponse::GroupLinkDeleted(resp) => Ok(Arc::new(resp)),
959                ApiDeleteGroupLinkResponse::ChatCmdError(resp) => {
960                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
961                }
962                ApiDeleteGroupLinkResponse::Undocumented(resp) => {
963                    Err(BadResponseError::Undocumented(resp).into())
964                }
965            }
966        }
967    }
968
969    /// ### Group link commands
970    ///
971    /// These commands can be used by bots that manage multiple public groups
972    ///
973    /// ----
974    ///
975    /// Get group link.
976    ///
977    /// *Network usage*: no.
978    ///
979    /// *Syntax:*
980    ///
981    /// ```
982    /// /_get link #<groupId>
983    /// ```
984    fn api_get_group_link(
985        &self,
986        group_id: i64,
987    ) -> impl Future<Output = Result<Arc<GroupLinkResponse>, Self::Error>> + Send {
988        async move {
989            let command = ApiGetGroupLink { group_id };
990            let json = self.send_raw(command.interpret()).await?;
991            // Safe to unwrap because unrecognized JSON goes to undocumented variant
992            let response = serde_json::from_value(json).unwrap();
993            match response {
994                ApiGetGroupLinkResponse::GroupLink(resp) => Ok(Arc::new(resp)),
995                ApiGetGroupLinkResponse::ChatCmdError(resp) => {
996                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
997                }
998                ApiGetGroupLinkResponse::Undocumented(resp) => {
999                    Err(BadResponseError::Undocumented(resp).into())
1000                }
1001            }
1002        }
1003    }
1004
1005    /// ### Connection commands
1006    ///
1007    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1008    ///
1009    /// ----
1010    ///
1011    /// Create 1-time invitation link.
1012    ///
1013    /// *Network usage*: interactive.
1014    ///
1015    /// *Syntax:*
1016    ///
1017    /// ```
1018    /// /_connect <userId>[ incognito=on]
1019    /// ```
1020    fn api_add_contact(
1021        &self,
1022        command: ApiAddContact,
1023    ) -> impl Future<Output = Result<Arc<InvitationResponse>, Self::Error>> + Send {
1024        async move {
1025            let json = self.send_raw(command.interpret()).await?;
1026            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1027            let response = serde_json::from_value(json).unwrap();
1028            match response {
1029                ApiAddContactResponse::Invitation(resp) => Ok(Arc::new(resp)),
1030                ApiAddContactResponse::ChatCmdError(resp) => {
1031                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1032                }
1033                ApiAddContactResponse::Undocumented(resp) => {
1034                    Err(BadResponseError::Undocumented(resp).into())
1035                }
1036            }
1037        }
1038    }
1039
1040    /// ### Connection commands
1041    ///
1042    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1043    ///
1044    /// ----
1045    ///
1046    /// Determine SimpleX link type and if the bot is already connected via this link.
1047    ///
1048    /// *Network usage*: interactive.
1049    ///
1050    /// *Syntax:*
1051    ///
1052    /// ```
1053    /// /_connect plan <userId> <connectionLink>
1054    /// ```
1055    fn api_connect_plan(
1056        &self,
1057        command: ApiConnectPlan,
1058    ) -> impl Future<Output = Result<Arc<ConnectionPlanResponse>, Self::Error>> + Send {
1059        async move {
1060            let json = self.send_raw(command.interpret()).await?;
1061            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1062            let response = serde_json::from_value(json).unwrap();
1063            match response {
1064                ApiConnectPlanResponse::ConnectionPlan(resp) => Ok(Arc::new(resp)),
1065                ApiConnectPlanResponse::ChatCmdError(resp) => {
1066                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1067                }
1068                ApiConnectPlanResponse::Undocumented(resp) => {
1069                    Err(BadResponseError::Undocumented(resp).into())
1070                }
1071            }
1072        }
1073    }
1074
1075    /// ### Connection commands
1076    ///
1077    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1078    ///
1079    /// ----
1080    ///
1081    /// Connect via prepared SimpleX link. The link can be 1-time invitation link, contact address or group link
1082    ///
1083    /// *Network usage*: interactive.
1084    ///
1085    /// *Syntax:*
1086    ///
1087    /// ```
1088    /// /_connect <userId>[ <str(preparedLink_)>]
1089    /// ```
1090    fn api_connect(
1091        &self,
1092        command: ApiConnect,
1093    ) -> impl Future<Output = Result<ApiConnectResponses, Self::Error>> + Send {
1094        async move {
1095            let json = self.send_raw(command.interpret()).await?;
1096            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1097            let response = serde_json::from_value(json).unwrap();
1098            match response {
1099                ApiConnectResponse::SentConfirmation(resp) => {
1100                    Ok(ApiConnectResponses::SentConfirmation(Arc::new(resp)))
1101                }
1102                ApiConnectResponse::ContactAlreadyExists(resp) => {
1103                    Ok(ApiConnectResponses::ContactAlreadyExists(Arc::new(resp)))
1104                }
1105                ApiConnectResponse::SentInvitation(resp) => {
1106                    Ok(ApiConnectResponses::SentInvitation(Arc::new(resp)))
1107                }
1108                ApiConnectResponse::ChatCmdError(resp) => {
1109                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1110                }
1111                ApiConnectResponse::Undocumented(resp) => {
1112                    Err(BadResponseError::Undocumented(resp).into())
1113                }
1114            }
1115        }
1116    }
1117
1118    /// ### Connection commands
1119    ///
1120    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1121    ///
1122    /// ----
1123    ///
1124    /// Connect via SimpleX link as string in the active user profile.
1125    ///
1126    /// *Network usage*: interactive.
1127    ///
1128    /// *Syntax:*
1129    ///
1130    /// ```
1131    /// /connect[ <connLink_>]
1132    /// ```
1133    fn connect(
1134        &self,
1135        command: Connect,
1136    ) -> impl Future<Output = Result<ConnectResponses, Self::Error>> + Send {
1137        async move {
1138            let json = self.send_raw(command.interpret()).await?;
1139            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1140            let response = serde_json::from_value(json).unwrap();
1141            match response {
1142                ConnectResponse::SentConfirmation(resp) => {
1143                    Ok(ConnectResponses::SentConfirmation(Arc::new(resp)))
1144                }
1145                ConnectResponse::ContactAlreadyExists(resp) => {
1146                    Ok(ConnectResponses::ContactAlreadyExists(Arc::new(resp)))
1147                }
1148                ConnectResponse::SentInvitation(resp) => {
1149                    Ok(ConnectResponses::SentInvitation(Arc::new(resp)))
1150                }
1151                ConnectResponse::ChatCmdError(resp) => {
1152                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1153                }
1154                ConnectResponse::Undocumented(resp) => {
1155                    Err(BadResponseError::Undocumented(resp).into())
1156                }
1157            }
1158        }
1159    }
1160
1161    /// ### Connection commands
1162    ///
1163    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1164    ///
1165    /// ----
1166    ///
1167    /// Accept contact request.
1168    ///
1169    /// *Network usage*: interactive.
1170    ///
1171    /// *Syntax:*
1172    ///
1173    /// ```
1174    /// /_accept <contactReqId>
1175    /// ```
1176    fn api_accept_contact(
1177        &self,
1178        contact_req_id: i64,
1179    ) -> impl Future<Output = Result<Arc<AcceptingContactRequestResponse>, Self::Error>> + Send
1180    {
1181        async move {
1182            let command = ApiAcceptContact { contact_req_id };
1183            let json = self.send_raw(command.interpret()).await?;
1184            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1185            let response = serde_json::from_value(json).unwrap();
1186            match response {
1187                ApiAcceptContactResponse::AcceptingContactRequest(resp) => Ok(Arc::new(resp)),
1188                ApiAcceptContactResponse::ChatCmdError(resp) => {
1189                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1190                }
1191                ApiAcceptContactResponse::Undocumented(resp) => {
1192                    Err(BadResponseError::Undocumented(resp).into())
1193                }
1194            }
1195        }
1196    }
1197
1198    /// ### Connection commands
1199    ///
1200    /// These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.
1201    ///
1202    /// ----
1203    ///
1204    /// Reject contact request. The user who sent the request is **not notified**.
1205    ///
1206    /// *Network usage*: no.
1207    ///
1208    /// *Syntax:*
1209    ///
1210    /// ```
1211    /// /_reject <contactReqId>
1212    /// ```
1213    fn api_reject_contact(
1214        &self,
1215        contact_req_id: i64,
1216    ) -> impl Future<Output = Result<Arc<ContactRequestRejectedResponse>, Self::Error>> + Send {
1217        async move {
1218            let command = ApiRejectContact { contact_req_id };
1219            let json = self.send_raw(command.interpret()).await?;
1220            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1221            let response = serde_json::from_value(json).unwrap();
1222            match response {
1223                ApiRejectContactResponse::ContactRequestRejected(resp) => Ok(Arc::new(resp)),
1224                ApiRejectContactResponse::ChatCmdError(resp) => {
1225                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1226                }
1227                ApiRejectContactResponse::Undocumented(resp) => {
1228                    Err(BadResponseError::Undocumented(resp).into())
1229                }
1230            }
1231        }
1232    }
1233
1234    /// ### Chat commands
1235    ///
1236    /// Commands to list and delete conversations.
1237    ///
1238    /// ----
1239    ///
1240    /// Get contacts.
1241    ///
1242    /// *Network usage*: no.
1243    ///
1244    /// *Syntax:*
1245    ///
1246    /// ```
1247    /// /_contacts <userId>
1248    /// ```
1249    fn api_list_contacts(
1250        &self,
1251        user_id: i64,
1252    ) -> impl Future<Output = Result<Arc<ContactsListResponse>, Self::Error>> + Send {
1253        async move {
1254            let command = ApiListContacts { user_id };
1255            let json = self.send_raw(command.interpret()).await?;
1256            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1257            let response = serde_json::from_value(json).unwrap();
1258            match response {
1259                ApiListContactsResponse::ContactsList(resp) => Ok(Arc::new(resp)),
1260                ApiListContactsResponse::ChatCmdError(resp) => {
1261                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1262                }
1263                ApiListContactsResponse::Undocumented(resp) => {
1264                    Err(BadResponseError::Undocumented(resp).into())
1265                }
1266            }
1267        }
1268    }
1269
1270    /// ### Chat commands
1271    ///
1272    /// Commands to list and delete conversations.
1273    ///
1274    /// ----
1275    ///
1276    /// Get groups.
1277    ///
1278    /// *Network usage*: no.
1279    ///
1280    /// *Syntax:*
1281    ///
1282    /// ```
1283    /// /_groups <userId>[ @<contactId_>][ <search>]
1284    /// ```
1285    fn api_list_groups(
1286        &self,
1287        command: ApiListGroups,
1288    ) -> impl Future<Output = Result<Arc<GroupsListResponse>, Self::Error>> + Send {
1289        async move {
1290            let json = self.send_raw(command.interpret()).await?;
1291            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1292            let response = serde_json::from_value(json).unwrap();
1293            match response {
1294                ApiListGroupsResponse::GroupsList(resp) => Ok(Arc::new(resp)),
1295                ApiListGroupsResponse::ChatCmdError(resp) => {
1296                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1297                }
1298                ApiListGroupsResponse::Undocumented(resp) => {
1299                    Err(BadResponseError::Undocumented(resp).into())
1300                }
1301            }
1302        }
1303    }
1304
1305    /// ### Chat commands
1306    ///
1307    /// Commands to list and delete conversations.
1308    ///
1309    /// ----
1310    ///
1311    /// Delete chat.
1312    ///
1313    /// *Network usage*: background.
1314    ///
1315    /// *Syntax:*
1316    ///
1317    /// ```
1318    /// /_delete <str(chatRef)> <str(chatDeleteMode)>
1319    /// ```
1320    fn api_delete_chat(
1321        &self,
1322        chat_ref: ChatRef,
1323        chat_delete_mode: ChatDeleteMode,
1324    ) -> impl Future<Output = Result<ApiDeleteChatResponses, Self::Error>> + Send {
1325        async move {
1326            let command = ApiDeleteChat {
1327                chat_ref,
1328                chat_delete_mode,
1329            };
1330            let json = self.send_raw(command.interpret()).await?;
1331            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1332            let response = serde_json::from_value(json).unwrap();
1333            match response {
1334                ApiDeleteChatResponse::ContactDeleted(resp) => {
1335                    Ok(ApiDeleteChatResponses::ContactDeleted(Arc::new(resp)))
1336                }
1337                ApiDeleteChatResponse::ContactConnectionDeleted(resp) => Ok(
1338                    ApiDeleteChatResponses::ContactConnectionDeleted(Arc::new(resp)),
1339                ),
1340                ApiDeleteChatResponse::GroupDeletedUser(resp) => {
1341                    Ok(ApiDeleteChatResponses::GroupDeletedUser(Arc::new(resp)))
1342                }
1343                ApiDeleteChatResponse::ChatCmdError(resp) => {
1344                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1345                }
1346                ApiDeleteChatResponse::Undocumented(resp) => {
1347                    Err(BadResponseError::Undocumented(resp).into())
1348                }
1349            }
1350        }
1351    }
1352
1353    /// ### User profile commands
1354    ///
1355    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1356    ///
1357    /// ----
1358    ///
1359    /// Get active user profile
1360    ///
1361    /// *Network usage*: no.
1362    ///
1363    /// *Syntax:*
1364    ///
1365    /// ```
1366    /// /user
1367    /// ```
1368    fn show_active_user(&self) -> impl Future<Output = Result<Arc<User>, Self::Error>> + Send {
1369        async move {
1370            let command = ShowActiveUser {};
1371            let json = self.send_raw(command.interpret()).await?;
1372            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1373            let response = serde_json::from_value(json).unwrap();
1374            match response {
1375                ShowActiveUserResponse::ActiveUser(resp) => Ok(Arc::new(resp.user)),
1376                ShowActiveUserResponse::ChatCmdError(resp) => {
1377                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1378                }
1379                ShowActiveUserResponse::Undocumented(resp) => {
1380                    Err(BadResponseError::Undocumented(resp).into())
1381                }
1382            }
1383        }
1384    }
1385
1386    /// ### User profile commands
1387    ///
1388    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1389    ///
1390    /// ----
1391    ///
1392    /// Create new user profile
1393    ///
1394    /// *Network usage*: no.
1395    ///
1396    /// *Syntax:*
1397    ///
1398    /// ```
1399    /// /_create user <json(newUser)>
1400    /// ```
1401    fn create_active_user(
1402        &self,
1403        new_user: NewUser,
1404    ) -> impl Future<Output = Result<Arc<User>, Self::Error>> + Send {
1405        async move {
1406            let command = CreateActiveUser { new_user };
1407            let json = self.send_raw(command.interpret()).await?;
1408            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1409            let response = serde_json::from_value(json).unwrap();
1410            match response {
1411                CreateActiveUserResponse::ActiveUser(resp) => Ok(Arc::new(resp.user)),
1412                CreateActiveUserResponse::ChatCmdError(resp) => {
1413                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1414                }
1415                CreateActiveUserResponse::Undocumented(resp) => {
1416                    Err(BadResponseError::Undocumented(resp).into())
1417                }
1418            }
1419        }
1420    }
1421
1422    /// ### User profile commands
1423    ///
1424    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1425    ///
1426    /// ----
1427    ///
1428    /// Get all user profiles
1429    ///
1430    /// *Network usage*: no.
1431    ///
1432    /// *Syntax:*
1433    ///
1434    /// ```
1435    /// /users
1436    /// ```
1437    fn list_users(&self) -> impl Future<Output = Result<Arc<Vec<UserInfo>>, Self::Error>> + Send {
1438        async move {
1439            let command = ListUsers {};
1440            let json = self.send_raw(command.interpret()).await?;
1441            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1442            let response = serde_json::from_value(json).unwrap();
1443            match response {
1444                ListUsersResponse::UsersList(resp) => Ok(Arc::new(resp.users)),
1445                ListUsersResponse::ChatCmdError(resp) => {
1446                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1447                }
1448                ListUsersResponse::Undocumented(resp) => {
1449                    Err(BadResponseError::Undocumented(resp).into())
1450                }
1451            }
1452        }
1453    }
1454
1455    /// ### User profile commands
1456    ///
1457    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1458    ///
1459    /// ----
1460    ///
1461    /// Set active user profile
1462    ///
1463    /// *Network usage*: no.
1464    ///
1465    /// *Syntax:*
1466    ///
1467    /// ```
1468    /// /_user <userId>[ <json(viewPwd)>]
1469    /// ```
1470    fn api_set_active_user(
1471        &self,
1472        command: ApiSetActiveUser,
1473    ) -> impl Future<Output = Result<Arc<User>, Self::Error>> + Send {
1474        async move {
1475            let json = self.send_raw(command.interpret()).await?;
1476            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1477            let response = serde_json::from_value(json).unwrap();
1478            match response {
1479                ApiSetActiveUserResponse::ActiveUser(resp) => Ok(Arc::new(resp.user)),
1480                ApiSetActiveUserResponse::ChatCmdError(resp) => {
1481                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1482                }
1483                ApiSetActiveUserResponse::Undocumented(resp) => {
1484                    Err(BadResponseError::Undocumented(resp).into())
1485                }
1486            }
1487        }
1488    }
1489
1490    /// ### User profile commands
1491    ///
1492    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1493    ///
1494    /// ----
1495    ///
1496    /// Delete user profile.
1497    ///
1498    /// *Network usage*: background.
1499    ///
1500    /// *Syntax:*
1501    ///
1502    /// ```
1503    /// /_delete user <userId> del_smp=on|off[ <json(viewPwd)>]
1504    /// ```
1505    fn api_delete_user(
1506        &self,
1507        command: ApiDeleteUser,
1508    ) -> impl Future<Output = Result<Arc<Option<User>>, Self::Error>> + Send {
1509        async move {
1510            let json = self.send_raw(command.interpret()).await?;
1511            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1512            let response = serde_json::from_value(json).unwrap();
1513            match response {
1514                ApiDeleteUserResponse::CmdOk(resp) => Ok(Arc::new(resp.user)),
1515                ApiDeleteUserResponse::ChatCmdError(resp) => {
1516                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1517                }
1518                ApiDeleteUserResponse::Undocumented(resp) => {
1519                    Err(BadResponseError::Undocumented(resp).into())
1520                }
1521            }
1522        }
1523    }
1524
1525    /// ### User profile commands
1526    ///
1527    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1528    ///
1529    /// ----
1530    ///
1531    /// Update user profile.
1532    ///
1533    /// *Network usage*: background.
1534    ///
1535    /// *Syntax:*
1536    ///
1537    /// ```
1538    /// /_profile <userId> <json(profile)>
1539    /// ```
1540    fn api_update_profile(
1541        &self,
1542        user_id: i64,
1543        profile: Profile,
1544    ) -> impl Future<Output = Result<ApiUpdateProfileResponses, Self::Error>> + Send {
1545        async move {
1546            let command = ApiUpdateProfile { user_id, profile };
1547            let json = self.send_raw(command.interpret()).await?;
1548            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1549            let response = serde_json::from_value(json).unwrap();
1550            match response {
1551                ApiUpdateProfileResponse::UserProfileUpdated(resp) => Ok(
1552                    ApiUpdateProfileResponses::UserProfileUpdated(Arc::new(resp)),
1553                ),
1554                ApiUpdateProfileResponse::UserProfileNoChange(resp) => Ok(
1555                    ApiUpdateProfileResponses::UserProfileNoChange(Arc::new(resp.user)),
1556                ),
1557                ApiUpdateProfileResponse::ChatCmdError(resp) => {
1558                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1559                }
1560                ApiUpdateProfileResponse::Undocumented(resp) => {
1561                    Err(BadResponseError::Undocumented(resp).into())
1562                }
1563            }
1564        }
1565    }
1566
1567    /// ### User profile commands
1568    ///
1569    /// Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).
1570    ///
1571    /// ----
1572    ///
1573    /// Configure chat preference overrides for the contact.
1574    ///
1575    /// *Network usage*: background.
1576    ///
1577    /// *Syntax:*
1578    ///
1579    /// ```
1580    /// /_set prefs @<contactId> <json(preferences)>
1581    /// ```
1582    fn api_set_contact_prefs(
1583        &self,
1584        contact_id: i64,
1585        preferences: Preferences,
1586    ) -> impl Future<Output = Result<Arc<ContactPrefsUpdatedResponse>, Self::Error>> + Send {
1587        async move {
1588            let command = ApiSetContactPrefs {
1589                contact_id,
1590                preferences,
1591            };
1592            let json = self.send_raw(command.interpret()).await?;
1593            // Safe to unwrap because unrecognized JSON goes to undocumented variant
1594            let response = serde_json::from_value(json).unwrap();
1595            match response {
1596                ApiSetContactPrefsResponse::ContactPrefsUpdated(resp) => Ok(Arc::new(resp)),
1597                ApiSetContactPrefsResponse::ChatCmdError(resp) => {
1598                    Err(BadResponseError::ChatCmdError(Arc::new(resp.chat_error)).into())
1599                }
1600                ApiSetContactPrefsResponse::Undocumented(resp) => {
1601                    Err(BadResponseError::Undocumented(resp).into())
1602                }
1603            }
1604        }
1605    }
1606}
1607
1608#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1609#[serde(tag = "type")]
1610pub enum ApiUpdateChatItemResponses {
1611    /// ChatItemUpdated: Message updated.
1612    #[serde(rename = "chatItemUpdated")]
1613    ChatItemUpdated(Arc<ChatItemUpdatedResponse>),
1614    /// ChatItemNotChanged: Message not changed.
1615    #[serde(rename = "chatItemNotChanged")]
1616    ChatItemNotChanged(Arc<ChatItemNotChangedResponse>),
1617}
1618
1619impl ApiUpdateChatItemResponses {
1620    pub fn chat_item_updated(&self) -> Option<&ChatItemUpdatedResponse> {
1621        if let Self::ChatItemUpdated(ret) = self {
1622            Some(ret)
1623        } else {
1624            None
1625        }
1626    }
1627
1628    pub fn chat_item_not_changed(&self) -> Option<&ChatItemNotChangedResponse> {
1629        if let Self::ChatItemNotChanged(ret) = self {
1630            Some(ret)
1631        } else {
1632            None
1633        }
1634    }
1635}
1636
1637#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1638#[serde(tag = "type")]
1639pub enum ReceiveFileResponses {
1640    /// RcvFileAccepted: File accepted to be received.
1641    #[serde(rename = "rcvFileAccepted")]
1642    RcvFileAccepted(Arc<RcvFileAcceptedResponse>),
1643    /// RcvFileAcceptedSndCancelled: File accepted, but no longer sent.
1644    #[serde(rename = "rcvFileAcceptedSndCancelled")]
1645    RcvFileAcceptedSndCancelled(Arc<RcvFileAcceptedSndCancelledResponse>),
1646}
1647
1648impl ReceiveFileResponses {
1649    pub fn rcv_file_accepted(&self) -> Option<&RcvFileAcceptedResponse> {
1650        if let Self::RcvFileAccepted(ret) = self {
1651            Some(ret)
1652        } else {
1653            None
1654        }
1655    }
1656
1657    pub fn rcv_file_accepted_snd_cancelled(&self) -> Option<&RcvFileAcceptedSndCancelledResponse> {
1658        if let Self::RcvFileAcceptedSndCancelled(ret) = self {
1659            Some(ret)
1660        } else {
1661            None
1662        }
1663    }
1664}
1665
1666#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1667#[serde(tag = "type")]
1668pub enum CancelFileResponses {
1669    /// SndFileCancelled: Cancelled sending file.
1670    #[serde(rename = "sndFileCancelled")]
1671    SndFileCancelled(Arc<SndFileCancelledResponse>),
1672    /// RcvFileCancelled: Cancelled receiving file.
1673    #[serde(rename = "rcvFileCancelled")]
1674    RcvFileCancelled(Arc<RcvFileCancelledResponse>),
1675}
1676
1677impl CancelFileResponses {
1678    pub fn snd_file_cancelled(&self) -> Option<&SndFileCancelledResponse> {
1679        if let Self::SndFileCancelled(ret) = self {
1680            Some(ret)
1681        } else {
1682            None
1683        }
1684    }
1685
1686    pub fn rcv_file_cancelled(&self) -> Option<&RcvFileCancelledResponse> {
1687        if let Self::RcvFileCancelled(ret) = self {
1688            Some(ret)
1689        } else {
1690            None
1691        }
1692    }
1693}
1694
1695#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1696#[serde(tag = "type")]
1697pub enum ApiConnectResponses {
1698    /// SentConfirmation: Confirmation sent to one-time invitation.
1699    #[serde(rename = "sentConfirmation")]
1700    SentConfirmation(Arc<SentConfirmationResponse>),
1701    /// ContactAlreadyExists: Contact already exists.
1702    #[serde(rename = "contactAlreadyExists")]
1703    ContactAlreadyExists(Arc<ContactAlreadyExistsResponse>),
1704    /// SentInvitation: Invitation sent to contact address.
1705    #[serde(rename = "sentInvitation")]
1706    SentInvitation(Arc<SentInvitationResponse>),
1707}
1708
1709impl ApiConnectResponses {
1710    pub fn sent_confirmation(&self) -> Option<&SentConfirmationResponse> {
1711        if let Self::SentConfirmation(ret) = self {
1712            Some(ret)
1713        } else {
1714            None
1715        }
1716    }
1717
1718    pub fn contact_already_exists(&self) -> Option<&ContactAlreadyExistsResponse> {
1719        if let Self::ContactAlreadyExists(ret) = self {
1720            Some(ret)
1721        } else {
1722            None
1723        }
1724    }
1725
1726    pub fn sent_invitation(&self) -> Option<&SentInvitationResponse> {
1727        if let Self::SentInvitation(ret) = self {
1728            Some(ret)
1729        } else {
1730            None
1731        }
1732    }
1733}
1734
1735#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1736#[serde(tag = "type")]
1737pub enum ConnectResponses {
1738    /// SentConfirmation: Confirmation sent to one-time invitation.
1739    #[serde(rename = "sentConfirmation")]
1740    SentConfirmation(Arc<SentConfirmationResponse>),
1741    /// ContactAlreadyExists: Contact already exists.
1742    #[serde(rename = "contactAlreadyExists")]
1743    ContactAlreadyExists(Arc<ContactAlreadyExistsResponse>),
1744    /// SentInvitation: Invitation sent to contact address.
1745    #[serde(rename = "sentInvitation")]
1746    SentInvitation(Arc<SentInvitationResponse>),
1747}
1748
1749impl ConnectResponses {
1750    pub fn sent_confirmation(&self) -> Option<&SentConfirmationResponse> {
1751        if let Self::SentConfirmation(ret) = self {
1752            Some(ret)
1753        } else {
1754            None
1755        }
1756    }
1757
1758    pub fn contact_already_exists(&self) -> Option<&ContactAlreadyExistsResponse> {
1759        if let Self::ContactAlreadyExists(ret) = self {
1760            Some(ret)
1761        } else {
1762            None
1763        }
1764    }
1765
1766    pub fn sent_invitation(&self) -> Option<&SentInvitationResponse> {
1767        if let Self::SentInvitation(ret) = self {
1768            Some(ret)
1769        } else {
1770            None
1771        }
1772    }
1773}
1774
1775#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1776#[serde(tag = "type")]
1777pub enum ApiDeleteChatResponses {
1778    /// ContactDeleted: Contact deleted.
1779    #[serde(rename = "contactDeleted")]
1780    ContactDeleted(Arc<ContactDeletedResponse>),
1781    /// ContactConnectionDeleted: Connection deleted.
1782    #[serde(rename = "contactConnectionDeleted")]
1783    ContactConnectionDeleted(Arc<ContactConnectionDeletedResponse>),
1784    /// GroupDeletedUser: User deleted group.
1785    #[serde(rename = "groupDeletedUser")]
1786    GroupDeletedUser(Arc<GroupDeletedUserResponse>),
1787}
1788
1789impl ApiDeleteChatResponses {
1790    pub fn contact_deleted(&self) -> Option<&ContactDeletedResponse> {
1791        if let Self::ContactDeleted(ret) = self {
1792            Some(ret)
1793        } else {
1794            None
1795        }
1796    }
1797
1798    pub fn contact_connection_deleted(&self) -> Option<&ContactConnectionDeletedResponse> {
1799        if let Self::ContactConnectionDeleted(ret) = self {
1800            Some(ret)
1801        } else {
1802            None
1803        }
1804    }
1805
1806    pub fn group_deleted_user(&self) -> Option<&GroupDeletedUserResponse> {
1807        if let Self::GroupDeletedUser(ret) = self {
1808            Some(ret)
1809        } else {
1810            None
1811        }
1812    }
1813}
1814
1815#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1816#[serde(tag = "type")]
1817pub enum ApiUpdateProfileResponses {
1818    /// UserProfileUpdated: User profile updated.
1819    #[serde(rename = "userProfileUpdated")]
1820    UserProfileUpdated(Arc<UserProfileUpdatedResponse>),
1821    /// UserProfileNoChange: User profile was not changed.
1822    #[serde(rename = "userProfileNoChange")]
1823    UserProfileNoChange(Arc<User>),
1824}
1825
1826impl ApiUpdateProfileResponses {
1827    pub fn user_profile_updated(&self) -> Option<&UserProfileUpdatedResponse> {
1828        if let Self::UserProfileUpdated(ret) = self {
1829            Some(ret)
1830        } else {
1831            None
1832        }
1833    }
1834
1835    pub fn user_profile_no_change(&self) -> Option<&User> {
1836        if let Self::UserProfileNoChange(ret) = self {
1837            Some(ret)
1838        } else {
1839            None
1840        }
1841    }
1842}
1843
1844#[derive(Debug)]
1845pub enum BadResponseError {
1846    ChatCmdError(Arc<ChatError>),
1847    Undocumented(BTreeMap<String, JsonObject>),
1848}
1849
1850impl std::error::Error for BadResponseError {}
1851
1852impl std::fmt::Display for BadResponseError {
1853    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1854        match self {
1855            Self::ChatCmdError(resp) => writeln!(
1856                f,
1857                "Bad server response:\n{}",
1858                serde_json::to_string_pretty(resp).unwrap()
1859            ),
1860            Self::Undocumented(resp) => writeln!(
1861                f,
1862                "Unexpected server response:\n{}",
1863                serde_json::to_string_pretty(resp).unwrap()
1864            ),
1865        }
1866    }
1867}
1868
1869pub enum UndocumentedResponse<T> {
1870    Documented(T),
1871    Undocumented(BTreeMap<String, JsonObject>),
1872}
1873
1874/// If you want to ~~suffer~~ handle undocumented responses you can use this extension trait
1875/// on client API return values which moves Undocumented from `Err` to `Ok` variant.
1876///
1877/// Example:
1878///
1879/// ```ignore
1880///     match client
1881///         .api_create_my_address(1)
1882///         .await
1883///         .allow_undocumented()?
1884///     {
1885///         UndocumentedResponse::Documented(resp) => {
1886///              // Process expected response...
1887///         }
1888///         UndocumentedResponse::Undocumented(resp) => {
1889///             // Do something with the unexpected response...
1890///         }
1891///     }
1892/// }
1893/// ```
1894pub trait AllowUndocumentedResponses<T, E> {
1895    fn allow_undocumented(self) -> Result<UndocumentedResponse<T>, E>;
1896}
1897
1898impl<T, E> AllowUndocumentedResponses<T, E> for Result<T, E>
1899where
1900    E: ClientApiError,
1901{
1902    fn allow_undocumented(self) -> Result<UndocumentedResponse<T>, E> {
1903        match self {
1904            Ok(resp) => Ok(UndocumentedResponse::Documented(resp)),
1905            Err(mut e) => match e.bad_response_mut() {
1906                Some(BadResponseError::Undocumented(btree_map)) => Ok(
1907                    UndocumentedResponse::Undocumented(std::mem::take(btree_map)),
1908                ),
1909                _ => Err(e),
1910            },
1911        }
1912    }
1913}