Skip to main content

simploxide_api_types/
commands.rs

1use super::*;
2use crate::utils::CommandSyntax;
3
4use std::fmt::Write;
5/// ### Address commands
6///
7/// Bots can use these commands to automatically check and create address when initialized
8///
9/// ----
10///
11/// Create bot address.
12///
13/// *Network usage*: interactive.
14///
15/// *Syntax:*
16///
17/// ```
18/// /_address <userId>
19/// ```
20#[derive(Debug, Clone, PartialEq)]
21#[cfg_attr(feature = "bon", derive(::bon::Builder))]
22pub struct ApiCreateMyAddress {
23    pub user_id: i64,
24}
25
26impl CommandSyntax for ApiCreateMyAddress {
27    const COMMAND_BUF_SIZE: usize = 64;
28
29    fn append_command_syntax(&self, buf: &mut String) {
30        buf.push_str("/_address ");
31        write!(buf, "{}", self.user_id).unwrap();
32    }
33}
34
35/// ### Address commands
36///
37/// Bots can use these commands to automatically check and create address when initialized
38///
39/// ----
40///
41/// Delete bot address.
42///
43/// *Network usage*: background.
44///
45/// *Syntax:*
46///
47/// ```
48/// /_delete_address <userId>
49/// ```
50#[derive(Debug, Clone, PartialEq)]
51#[cfg_attr(feature = "bon", derive(::bon::Builder))]
52pub struct ApiDeleteMyAddress {
53    pub user_id: i64,
54}
55
56impl CommandSyntax for ApiDeleteMyAddress {
57    const COMMAND_BUF_SIZE: usize = 64;
58
59    fn append_command_syntax(&self, buf: &mut String) {
60        buf.push_str("/_delete_address ");
61        write!(buf, "{}", self.user_id).unwrap();
62    }
63}
64
65/// ### Address commands
66///
67/// Bots can use these commands to automatically check and create address when initialized
68///
69/// ----
70///
71/// Get bot address and settings.
72///
73/// *Network usage*: no.
74///
75/// *Syntax:*
76///
77/// ```
78/// /_show_address <userId>
79/// ```
80#[derive(Debug, Clone, PartialEq)]
81#[cfg_attr(feature = "bon", derive(::bon::Builder))]
82pub struct ApiShowMyAddress {
83    pub user_id: i64,
84}
85
86impl CommandSyntax for ApiShowMyAddress {
87    const COMMAND_BUF_SIZE: usize = 64;
88
89    fn append_command_syntax(&self, buf: &mut String) {
90        buf.push_str("/_show_address ");
91        write!(buf, "{}", self.user_id).unwrap();
92    }
93}
94
95/// ### Address commands
96///
97/// Bots can use these commands to automatically check and create address when initialized
98///
99/// ----
100///
101/// Add address to bot profile.
102///
103/// *Network usage*: interactive.
104///
105/// *Syntax:*
106///
107/// ```
108/// /_profile_address <userId> on|off
109/// ```
110#[derive(Debug, Clone, PartialEq)]
111#[cfg_attr(feature = "bon", derive(::bon::Builder))]
112pub struct ApiSetProfileAddress {
113    pub user_id: i64,
114    pub enable: bool,
115}
116
117impl CommandSyntax for ApiSetProfileAddress {
118    const COMMAND_BUF_SIZE: usize = 64;
119
120    fn append_command_syntax(&self, buf: &mut String) {
121        buf.push_str("/_profile_address ");
122        write!(buf, "{}", self.user_id).unwrap();
123        buf.push(' ');
124        if self.enable {
125            buf.push_str("on");
126        } else {
127            buf.push_str("off");
128        }
129    }
130}
131
132/// ### Address commands
133///
134/// Bots can use these commands to automatically check and create address when initialized
135///
136/// ----
137///
138/// Set bot address settings.
139///
140/// *Network usage*: interactive.
141///
142/// *Syntax:*
143///
144/// ```
145/// /_address_settings <userId> <json(settings)>
146/// ```
147#[derive(Debug, Clone, PartialEq)]
148#[cfg_attr(feature = "bon", derive(::bon::Builder))]
149pub struct ApiSetAddressSettings {
150    pub user_id: i64,
151    pub settings: AddressSettings,
152}
153
154impl CommandSyntax for ApiSetAddressSettings {
155    const COMMAND_BUF_SIZE: usize = 1024;
156
157    fn append_command_syntax(&self, buf: &mut String) {
158        buf.push_str("/_address_settings ");
159        write!(buf, "{}", self.user_id).unwrap();
160        buf.push(' ');
161        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
162        unsafe {
163            serde_json::to_writer(buf.as_mut_vec(), &self.settings).unwrap();
164        }
165    }
166}
167
168/// ### Message commands
169///
170/// Commands to send, update, delete, moderate messages and set message reactions
171///
172/// ----
173///
174/// Send messages.
175///
176/// *Network usage*: background.
177///
178/// *Syntax:*
179///
180/// ```
181/// /_send <str(sendRef)>[ live=on][ ttl=<ttl>] json <json(composedMessages)>
182/// ```
183#[derive(Debug, Clone, PartialEq)]
184#[cfg_attr(feature = "bon", derive(::bon::Builder))]
185pub struct ApiSendMessages {
186    pub send_ref: ChatRef,
187    pub live_message: bool,
188    pub ttl: Option<i32>,
189    pub composed_messages: Vec<ComposedMessage>,
190}
191
192impl CommandSyntax for ApiSendMessages {
193    const COMMAND_BUF_SIZE: usize = 1024;
194
195    fn append_command_syntax(&self, buf: &mut String) {
196        buf.push_str("/_send ");
197        self.send_ref.append_command_syntax(buf);
198        if self.live_message {
199            buf.push(' ');
200            buf.push_str("live=");
201            buf.push_str("on");
202        }
203        if let Some(ttl) = &self.ttl {
204            buf.push(' ');
205            buf.push_str("ttl=");
206            write!(buf, "{}", ttl).unwrap();
207        }
208        buf.push(' ');
209        buf.push_str("json ");
210        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
211        unsafe {
212            serde_json::to_writer(buf.as_mut_vec(), &self.composed_messages).unwrap();
213        }
214    }
215}
216
217/// ### Message commands
218///
219/// Commands to send, update, delete, moderate messages and set message reactions
220///
221/// ----
222///
223/// Update message.
224///
225/// *Network usage*: background.
226///
227/// *Syntax:*
228///
229/// ```
230/// /_update item <str(chatRef)> <chatItemId>[ live=on] json <json(updatedMessage)>
231/// ```
232#[derive(Debug, Clone, PartialEq)]
233#[cfg_attr(feature = "bon", derive(::bon::Builder))]
234pub struct ApiUpdateChatItem {
235    pub chat_ref: ChatRef,
236    pub chat_item_id: i64,
237    pub live_message: bool,
238    pub updated_message: UpdatedMessage,
239}
240
241impl CommandSyntax for ApiUpdateChatItem {
242    const COMMAND_BUF_SIZE: usize = 1024;
243
244    fn append_command_syntax(&self, buf: &mut String) {
245        buf.push_str("/_update ");
246        buf.push_str("item ");
247        self.chat_ref.append_command_syntax(buf);
248        buf.push(' ');
249        write!(buf, "{}", self.chat_item_id).unwrap();
250        if self.live_message {
251            buf.push(' ');
252            buf.push_str("live=");
253            buf.push_str("on");
254        }
255        buf.push(' ');
256        buf.push_str("json ");
257        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
258        unsafe {
259            serde_json::to_writer(buf.as_mut_vec(), &self.updated_message).unwrap();
260        }
261    }
262}
263
264/// ### Message commands
265///
266/// Commands to send, update, delete, moderate messages and set message reactions
267///
268/// ----
269///
270/// Delete message.
271///
272/// *Network usage*: background.
273///
274/// *Syntax:*
275///
276/// ```
277/// /_delete item <str(chatRef)> <chatItemIds[0]>[,<chatItemIds[1]>...] broadcast|internal|internalMark
278/// ```
279#[derive(Debug, Clone, PartialEq)]
280#[cfg_attr(feature = "bon", derive(::bon::Builder))]
281pub struct ApiDeleteChatItem {
282    pub chat_ref: ChatRef,
283    pub chat_item_ids: Vec<i64>,
284    pub delete_mode: CIDeleteMode,
285}
286
287impl CommandSyntax for ApiDeleteChatItem {
288    const COMMAND_BUF_SIZE: usize = 256;
289
290    fn append_command_syntax(&self, buf: &mut String) {
291        buf.push_str("/_delete ");
292        buf.push_str("item ");
293        self.chat_ref.append_command_syntax(buf);
294        buf.push(' ');
295        let mut iter = self.chat_item_ids.iter();
296        if let Some(el) = iter.next() {
297            write!(buf, "{el}").unwrap();
298        }
299        for el in iter {
300            buf.push(',');
301            write!(buf, "{el}").unwrap();
302        }
303        buf.push(' ');
304        match self.delete_mode {
305            CIDeleteMode::Broadcast => {
306                buf.push_str("broadcast");
307            }
308            CIDeleteMode::Internal => {
309                buf.push_str("internal");
310            }
311            CIDeleteMode::InternalMark => {
312                buf.push_str("internalMark");
313            }
314        }
315    }
316}
317
318/// ### Message commands
319///
320/// Commands to send, update, delete, moderate messages and set message reactions
321///
322/// ----
323///
324/// Moderate message. Requires Moderator role (and higher than message author's).
325///
326/// *Network usage*: background.
327///
328/// *Syntax:*
329///
330/// ```
331/// /_delete member item #<groupId> <chatItemIds[0]>[,<chatItemIds[1]>...]
332/// ```
333#[derive(Debug, Clone, PartialEq)]
334#[cfg_attr(feature = "bon", derive(::bon::Builder))]
335pub struct ApiDeleteMemberChatItem {
336    pub group_id: i64,
337    pub chat_item_ids: Vec<i64>,
338}
339
340impl CommandSyntax for ApiDeleteMemberChatItem {
341    const COMMAND_BUF_SIZE: usize = 256;
342
343    fn append_command_syntax(&self, buf: &mut String) {
344        buf.push_str("/_delete ");
345        buf.push_str("member ");
346        buf.push_str("item ");
347        buf.push('#');
348        write!(buf, "{}", self.group_id).unwrap();
349        buf.push(' ');
350        let mut iter = self.chat_item_ids.iter();
351        if let Some(el) = iter.next() {
352            write!(buf, "{el}").unwrap();
353        }
354        for el in iter {
355            buf.push(',');
356            write!(buf, "{el}").unwrap();
357        }
358    }
359}
360
361/// ### Message commands
362///
363/// Commands to send, update, delete, moderate messages and set message reactions
364///
365/// ----
366///
367/// Add/remove message reaction.
368///
369/// *Network usage*: background.
370///
371/// *Syntax:*
372///
373/// ```
374/// /_reaction <str(chatRef)> <chatItemId> on|off <json(reaction)>
375/// ```
376#[derive(Debug, Clone, PartialEq)]
377#[cfg_attr(feature = "bon", derive(::bon::Builder))]
378pub struct ApiChatItemReaction {
379    pub chat_ref: ChatRef,
380    pub chat_item_id: i64,
381    pub add: bool,
382    pub reaction: MsgReaction,
383}
384
385impl CommandSyntax for ApiChatItemReaction {
386    const COMMAND_BUF_SIZE: usize = 1024;
387
388    fn append_command_syntax(&self, buf: &mut String) {
389        buf.push_str("/_reaction ");
390        self.chat_ref.append_command_syntax(buf);
391        buf.push(' ');
392        write!(buf, "{}", self.chat_item_id).unwrap();
393        buf.push(' ');
394        if self.add {
395            buf.push_str("on");
396        } else {
397            buf.push_str("off");
398        }
399        buf.push(' ');
400        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
401        unsafe {
402            serde_json::to_writer(buf.as_mut_vec(), &self.reaction).unwrap();
403        }
404    }
405}
406
407/// ### File commands
408///
409/// Commands to receive and to cancel files. Files are sent as part of the message, there are no separate commands to send files.
410///
411/// ----
412///
413/// Receive file.
414///
415/// *Network usage*: no.
416///
417/// *Syntax:*
418///
419/// ```
420/// /freceive <fileId>[ approved_relays=on][ encrypt=on|off][ inline=on|off][ <filePath>]
421/// ```
422#[derive(Debug, Clone, PartialEq)]
423#[cfg_attr(feature = "bon", derive(::bon::Builder))]
424pub struct ReceiveFile {
425    pub file_id: i64,
426    pub user_approved_relays: bool,
427    pub store_encrypted: Option<bool>,
428    pub file_inline: Option<bool>,
429    pub file_path: Option<String>,
430}
431
432impl CommandSyntax for ReceiveFile {
433    const COMMAND_BUF_SIZE: usize = 256;
434
435    fn append_command_syntax(&self, buf: &mut String) {
436        buf.push_str("/freceive ");
437        write!(buf, "{}", self.file_id).unwrap();
438        if self.user_approved_relays {
439            buf.push(' ');
440            buf.push_str("approved_relays=");
441            buf.push_str("on");
442        }
443        if let Some(store_encrypted) = &self.store_encrypted {
444            buf.push(' ');
445            buf.push_str("encrypt=");
446            if *store_encrypted {
447                buf.push_str("on");
448            } else {
449                buf.push_str("off");
450            }
451        }
452        if let Some(file_inline) = &self.file_inline {
453            buf.push(' ');
454            buf.push_str("inline=");
455            if *file_inline {
456                buf.push_str("on");
457            } else {
458                buf.push_str("off");
459            }
460        }
461        if let Some(file_path) = &self.file_path {
462            buf.push(' ');
463            write!(buf, "{}", file_path).unwrap();
464        }
465    }
466}
467
468/// ### File commands
469///
470/// Commands to receive and to cancel files. Files are sent as part of the message, there are no separate commands to send files.
471///
472/// ----
473///
474/// Cancel file.
475///
476/// *Network usage*: background.
477///
478/// *Syntax:*
479///
480/// ```
481/// /fcancel <fileId>
482/// ```
483#[derive(Debug, Clone, PartialEq)]
484#[cfg_attr(feature = "bon", derive(::bon::Builder))]
485pub struct CancelFile {
486    pub file_id: i64,
487}
488
489impl CommandSyntax for CancelFile {
490    const COMMAND_BUF_SIZE: usize = 64;
491
492    fn append_command_syntax(&self, buf: &mut String) {
493        buf.push_str("/fcancel ");
494        write!(buf, "{}", self.file_id).unwrap();
495    }
496}
497
498/// ### Group commands
499///
500/// 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.
501///
502/// ----
503///
504/// Add contact to group. Requires bot to have Admin role.
505///
506/// *Network usage*: interactive.
507///
508/// *Syntax:*
509///
510/// ```
511/// /_add #<groupId> <contactId> observer|author|member|moderator|admin|owner
512/// ```
513#[derive(Debug, Clone, PartialEq)]
514#[cfg_attr(feature = "bon", derive(::bon::Builder))]
515pub struct ApiAddMember {
516    pub group_id: i64,
517    pub contact_id: i64,
518    pub member_role: GroupMemberRole,
519}
520
521impl CommandSyntax for ApiAddMember {
522    const COMMAND_BUF_SIZE: usize = 256;
523
524    fn append_command_syntax(&self, buf: &mut String) {
525        buf.push_str("/_add ");
526        buf.push('#');
527        write!(buf, "{}", self.group_id).unwrap();
528        buf.push(' ');
529        write!(buf, "{}", self.contact_id).unwrap();
530        buf.push(' ');
531        match self.member_role {
532            GroupMemberRole::Observer => {
533                buf.push_str("observer");
534            }
535            GroupMemberRole::Author => {
536                buf.push_str("author");
537            }
538            GroupMemberRole::Member => {
539                buf.push_str("member");
540            }
541            GroupMemberRole::Moderator => {
542                buf.push_str("moderator");
543            }
544            GroupMemberRole::Admin => {
545                buf.push_str("admin");
546            }
547            GroupMemberRole::Owner => {
548                buf.push_str("owner");
549            }
550        }
551    }
552}
553
554/// ### Group commands
555///
556/// 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.
557///
558/// ----
559///
560/// Join group.
561///
562/// *Network usage*: interactive.
563///
564/// *Syntax:*
565///
566/// ```
567/// /_join #<groupId>
568/// ```
569#[derive(Debug, Clone, PartialEq)]
570#[cfg_attr(feature = "bon", derive(::bon::Builder))]
571pub struct ApiJoinGroup {
572    pub group_id: i64,
573}
574
575impl CommandSyntax for ApiJoinGroup {
576    const COMMAND_BUF_SIZE: usize = 64;
577
578    fn append_command_syntax(&self, buf: &mut String) {
579        buf.push_str("/_join ");
580        buf.push('#');
581        write!(buf, "{}", self.group_id).unwrap();
582    }
583}
584
585/// ### Group commands
586///
587/// 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.
588///
589/// ----
590///
591/// Accept group member. Requires Admin role.
592///
593/// *Network usage*: background.
594///
595/// *Syntax:*
596///
597/// ```
598/// /_accept member #<groupId> <groupMemberId> observer|author|member|moderator|admin|owner
599/// ```
600#[derive(Debug, Clone, PartialEq)]
601#[cfg_attr(feature = "bon", derive(::bon::Builder))]
602pub struct ApiAcceptMember {
603    pub group_id: i64,
604    pub group_member_id: i64,
605    pub member_role: GroupMemberRole,
606}
607
608impl CommandSyntax for ApiAcceptMember {
609    const COMMAND_BUF_SIZE: usize = 256;
610
611    fn append_command_syntax(&self, buf: &mut String) {
612        buf.push_str("/_accept ");
613        buf.push_str("member ");
614        buf.push('#');
615        write!(buf, "{}", self.group_id).unwrap();
616        buf.push(' ');
617        write!(buf, "{}", self.group_member_id).unwrap();
618        buf.push(' ');
619        match self.member_role {
620            GroupMemberRole::Observer => {
621                buf.push_str("observer");
622            }
623            GroupMemberRole::Author => {
624                buf.push_str("author");
625            }
626            GroupMemberRole::Member => {
627                buf.push_str("member");
628            }
629            GroupMemberRole::Moderator => {
630                buf.push_str("moderator");
631            }
632            GroupMemberRole::Admin => {
633                buf.push_str("admin");
634            }
635            GroupMemberRole::Owner => {
636                buf.push_str("owner");
637            }
638        }
639    }
640}
641
642/// ### Group commands
643///
644/// 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.
645///
646/// ----
647///
648/// Set members role. Requires Admin role.
649///
650/// *Network usage*: background.
651///
652/// *Syntax:*
653///
654/// ```
655/// /_member role #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...] observer|author|member|moderator|admin|owner
656/// ```
657#[derive(Debug, Clone, PartialEq)]
658#[cfg_attr(feature = "bon", derive(::bon::Builder))]
659pub struct ApiMembersRole {
660    pub group_id: i64,
661    pub group_member_ids: Vec<i64>,
662    pub member_role: GroupMemberRole,
663}
664
665impl CommandSyntax for ApiMembersRole {
666    const COMMAND_BUF_SIZE: usize = 256;
667
668    fn append_command_syntax(&self, buf: &mut String) {
669        buf.push_str("/_member ");
670        buf.push_str("role ");
671        buf.push('#');
672        write!(buf, "{}", self.group_id).unwrap();
673        buf.push(' ');
674        let mut iter = self.group_member_ids.iter();
675        if let Some(el) = iter.next() {
676            write!(buf, "{el}").unwrap();
677        }
678        for el in iter {
679            buf.push(',');
680            write!(buf, "{el}").unwrap();
681        }
682        buf.push(' ');
683        match self.member_role {
684            GroupMemberRole::Observer => {
685                buf.push_str("observer");
686            }
687            GroupMemberRole::Author => {
688                buf.push_str("author");
689            }
690            GroupMemberRole::Member => {
691                buf.push_str("member");
692            }
693            GroupMemberRole::Moderator => {
694                buf.push_str("moderator");
695            }
696            GroupMemberRole::Admin => {
697                buf.push_str("admin");
698            }
699            GroupMemberRole::Owner => {
700                buf.push_str("owner");
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/// Block members. Requires Moderator role.
713///
714/// *Network usage*: background.
715///
716/// *Syntax:*
717///
718/// ```
719/// /_block #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...] blocked=on|off
720/// ```
721#[derive(Debug, Clone, PartialEq)]
722#[cfg_attr(feature = "bon", derive(::bon::Builder))]
723pub struct ApiBlockMembersForAll {
724    pub group_id: i64,
725    pub group_member_ids: Vec<i64>,
726    pub blocked: bool,
727}
728
729impl CommandSyntax for ApiBlockMembersForAll {
730    const COMMAND_BUF_SIZE: usize = 256;
731
732    fn append_command_syntax(&self, buf: &mut String) {
733        buf.push_str("/_block ");
734        buf.push('#');
735        write!(buf, "{}", self.group_id).unwrap();
736        buf.push(' ');
737        let mut iter = self.group_member_ids.iter();
738        if let Some(el) = iter.next() {
739            write!(buf, "{el}").unwrap();
740        }
741        for el in iter {
742            buf.push(',');
743            write!(buf, "{el}").unwrap();
744        }
745        buf.push(' ');
746        buf.push_str("blocked=");
747        if self.blocked {
748            buf.push_str("on");
749        } else {
750            buf.push_str("off");
751        }
752    }
753}
754
755/// ### Group commands
756///
757/// 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.
758///
759/// ----
760///
761/// Remove members. Requires Admin role.
762///
763/// *Network usage*: background.
764///
765/// *Syntax:*
766///
767/// ```
768/// /_remove #<groupId> <groupMemberIds[0]>[,<groupMemberIds[1]>...][ messages=on]
769/// ```
770#[derive(Debug, Clone, PartialEq)]
771#[cfg_attr(feature = "bon", derive(::bon::Builder))]
772pub struct ApiRemoveMembers {
773    pub group_id: i64,
774    pub group_member_ids: Vec<i64>,
775    pub with_messages: bool,
776}
777
778impl CommandSyntax for ApiRemoveMembers {
779    const COMMAND_BUF_SIZE: usize = 256;
780
781    fn append_command_syntax(&self, buf: &mut String) {
782        buf.push_str("/_remove ");
783        buf.push('#');
784        write!(buf, "{}", self.group_id).unwrap();
785        buf.push(' ');
786        let mut iter = self.group_member_ids.iter();
787        if let Some(el) = iter.next() {
788            write!(buf, "{el}").unwrap();
789        }
790        for el in iter {
791            buf.push(',');
792            write!(buf, "{el}").unwrap();
793        }
794        if self.with_messages {
795            buf.push(' ');
796            buf.push_str("messages=");
797            buf.push_str("on");
798        }
799    }
800}
801
802/// ### Group commands
803///
804/// 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.
805///
806/// ----
807///
808/// Leave group.
809///
810/// *Network usage*: background.
811///
812/// *Syntax:*
813///
814/// ```
815/// /_leave #<groupId>
816/// ```
817#[derive(Debug, Clone, PartialEq)]
818#[cfg_attr(feature = "bon", derive(::bon::Builder))]
819pub struct ApiLeaveGroup {
820    pub group_id: i64,
821}
822
823impl CommandSyntax for ApiLeaveGroup {
824    const COMMAND_BUF_SIZE: usize = 64;
825
826    fn append_command_syntax(&self, buf: &mut String) {
827        buf.push_str("/_leave ");
828        buf.push('#');
829        write!(buf, "{}", self.group_id).unwrap();
830    }
831}
832
833/// ### Group commands
834///
835/// 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.
836///
837/// ----
838///
839/// Get group members.
840///
841/// *Network usage*: no.
842///
843/// *Syntax:*
844///
845/// ```
846/// /_members #<groupId>
847/// ```
848#[derive(Debug, Clone, PartialEq)]
849#[cfg_attr(feature = "bon", derive(::bon::Builder))]
850pub struct ApiListMembers {
851    pub group_id: i64,
852}
853
854impl CommandSyntax for ApiListMembers {
855    const COMMAND_BUF_SIZE: usize = 64;
856
857    fn append_command_syntax(&self, buf: &mut String) {
858        buf.push_str("/_members ");
859        buf.push('#');
860        write!(buf, "{}", self.group_id).unwrap();
861    }
862}
863
864/// ### Group commands
865///
866/// 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.
867///
868/// ----
869///
870/// Create group.
871///
872/// *Network usage*: no.
873///
874/// *Syntax:*
875///
876/// ```
877/// /_group <userId>[ incognito=on] <json(groupProfile)>
878/// ```
879#[derive(Debug, Clone, PartialEq)]
880#[cfg_attr(feature = "bon", derive(::bon::Builder))]
881pub struct ApiNewGroup {
882    pub user_id: i64,
883    pub incognito: bool,
884    pub group_profile: GroupProfile,
885}
886
887impl CommandSyntax for ApiNewGroup {
888    const COMMAND_BUF_SIZE: usize = 1024;
889
890    fn append_command_syntax(&self, buf: &mut String) {
891        buf.push_str("/_group ");
892        write!(buf, "{}", self.user_id).unwrap();
893        if self.incognito {
894            buf.push(' ');
895            buf.push_str("incognito=");
896            buf.push_str("on");
897        }
898        buf.push(' ');
899        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
900        unsafe {
901            serde_json::to_writer(buf.as_mut_vec(), &self.group_profile).unwrap();
902        }
903    }
904}
905
906/// ### Group commands
907///
908/// 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.
909///
910/// ----
911///
912/// Update group profile.
913///
914/// *Network usage*: background.
915///
916/// *Syntax:*
917///
918/// ```
919/// /_group_profile #<groupId> <json(groupProfile)>
920/// ```
921#[derive(Debug, Clone, PartialEq)]
922#[cfg_attr(feature = "bon", derive(::bon::Builder))]
923pub struct ApiUpdateGroupProfile {
924    pub group_id: i64,
925    pub group_profile: GroupProfile,
926}
927
928impl CommandSyntax for ApiUpdateGroupProfile {
929    const COMMAND_BUF_SIZE: usize = 1024;
930
931    fn append_command_syntax(&self, buf: &mut String) {
932        buf.push_str("/_group_profile ");
933        buf.push('#');
934        write!(buf, "{}", self.group_id).unwrap();
935        buf.push(' ');
936        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
937        unsafe {
938            serde_json::to_writer(buf.as_mut_vec(), &self.group_profile).unwrap();
939        }
940    }
941}
942
943/// ### Group link commands
944///
945/// These commands can be used by bots that manage multiple public groups
946///
947/// ----
948///
949/// Create group link.
950///
951/// *Network usage*: interactive.
952///
953/// *Syntax:*
954///
955/// ```
956/// /_create link #<groupId> observer|author|member|moderator|admin|owner
957/// ```
958#[derive(Debug, Clone, PartialEq)]
959#[cfg_attr(feature = "bon", derive(::bon::Builder))]
960pub struct ApiCreateGroupLink {
961    pub group_id: i64,
962    pub member_role: GroupMemberRole,
963}
964
965impl CommandSyntax for ApiCreateGroupLink {
966    const COMMAND_BUF_SIZE: usize = 64;
967
968    fn append_command_syntax(&self, buf: &mut String) {
969        buf.push_str("/_create ");
970        buf.push_str("link ");
971        buf.push('#');
972        write!(buf, "{}", self.group_id).unwrap();
973        buf.push(' ');
974        match self.member_role {
975            GroupMemberRole::Observer => {
976                buf.push_str("observer");
977            }
978            GroupMemberRole::Author => {
979                buf.push_str("author");
980            }
981            GroupMemberRole::Member => {
982                buf.push_str("member");
983            }
984            GroupMemberRole::Moderator => {
985                buf.push_str("moderator");
986            }
987            GroupMemberRole::Admin => {
988                buf.push_str("admin");
989            }
990            GroupMemberRole::Owner => {
991                buf.push_str("owner");
992            }
993        }
994    }
995}
996
997/// ### Group link commands
998///
999/// These commands can be used by bots that manage multiple public groups
1000///
1001/// ----
1002///
1003/// Set member role for group link.
1004///
1005/// *Network usage*: no.
1006///
1007/// *Syntax:*
1008///
1009/// ```
1010/// /_set link role #<groupId> observer|author|member|moderator|admin|owner
1011/// ```
1012#[derive(Debug, Clone, PartialEq)]
1013#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1014pub struct ApiGroupLinkMemberRole {
1015    pub group_id: i64,
1016    pub member_role: GroupMemberRole,
1017}
1018
1019impl CommandSyntax for ApiGroupLinkMemberRole {
1020    const COMMAND_BUF_SIZE: usize = 64;
1021
1022    fn append_command_syntax(&self, buf: &mut String) {
1023        buf.push_str("/_set ");
1024        buf.push_str("link ");
1025        buf.push_str("role ");
1026        buf.push('#');
1027        write!(buf, "{}", self.group_id).unwrap();
1028        buf.push(' ');
1029        match self.member_role {
1030            GroupMemberRole::Observer => {
1031                buf.push_str("observer");
1032            }
1033            GroupMemberRole::Author => {
1034                buf.push_str("author");
1035            }
1036            GroupMemberRole::Member => {
1037                buf.push_str("member");
1038            }
1039            GroupMemberRole::Moderator => {
1040                buf.push_str("moderator");
1041            }
1042            GroupMemberRole::Admin => {
1043                buf.push_str("admin");
1044            }
1045            GroupMemberRole::Owner => {
1046                buf.push_str("owner");
1047            }
1048        }
1049    }
1050}
1051
1052/// ### Group link commands
1053///
1054/// These commands can be used by bots that manage multiple public groups
1055///
1056/// ----
1057///
1058/// Delete group link.
1059///
1060/// *Network usage*: background.
1061///
1062/// *Syntax:*
1063///
1064/// ```
1065/// /_delete link #<groupId>
1066/// ```
1067#[derive(Debug, Clone, PartialEq)]
1068#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1069pub struct ApiDeleteGroupLink {
1070    pub group_id: i64,
1071}
1072
1073impl CommandSyntax for ApiDeleteGroupLink {
1074    const COMMAND_BUF_SIZE: usize = 64;
1075
1076    fn append_command_syntax(&self, buf: &mut String) {
1077        buf.push_str("/_delete ");
1078        buf.push_str("link ");
1079        buf.push('#');
1080        write!(buf, "{}", self.group_id).unwrap();
1081    }
1082}
1083
1084/// ### Group link commands
1085///
1086/// These commands can be used by bots that manage multiple public groups
1087///
1088/// ----
1089///
1090/// Get group link.
1091///
1092/// *Network usage*: no.
1093///
1094/// *Syntax:*
1095///
1096/// ```
1097/// /_get link #<groupId>
1098/// ```
1099#[derive(Debug, Clone, PartialEq)]
1100#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1101pub struct ApiGetGroupLink {
1102    pub group_id: i64,
1103}
1104
1105impl CommandSyntax for ApiGetGroupLink {
1106    const COMMAND_BUF_SIZE: usize = 64;
1107
1108    fn append_command_syntax(&self, buf: &mut String) {
1109        buf.push_str("/_get ");
1110        buf.push_str("link ");
1111        buf.push('#');
1112        write!(buf, "{}", self.group_id).unwrap();
1113    }
1114}
1115
1116/// ### Connection commands
1117///
1118/// 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.
1119///
1120/// ----
1121///
1122/// Create 1-time invitation link.
1123///
1124/// *Network usage*: interactive.
1125///
1126/// *Syntax:*
1127///
1128/// ```
1129/// /_connect <userId>[ incognito=on]
1130/// ```
1131#[derive(Debug, Clone, PartialEq)]
1132#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1133pub struct ApiAddContact {
1134    pub user_id: i64,
1135    pub incognito: bool,
1136}
1137
1138impl CommandSyntax for ApiAddContact {
1139    const COMMAND_BUF_SIZE: usize = 64;
1140
1141    fn append_command_syntax(&self, buf: &mut String) {
1142        buf.push_str("/_connect ");
1143        write!(buf, "{}", self.user_id).unwrap();
1144        if self.incognito {
1145            buf.push(' ');
1146            buf.push_str("incognito=");
1147            buf.push_str("on");
1148        }
1149    }
1150}
1151
1152/// ### Connection commands
1153///
1154/// 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.
1155///
1156/// ----
1157///
1158/// Determine SimpleX link type and if the bot is already connected via this link.
1159///
1160/// *Network usage*: interactive.
1161///
1162/// *Syntax:*
1163///
1164/// ```
1165/// /_connect plan <userId> <connectionLink>
1166/// ```
1167#[derive(Debug, Clone, PartialEq)]
1168#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1169pub struct ApiConnectPlan {
1170    pub user_id: i64,
1171    pub connection_link: Option<String>,
1172}
1173
1174impl CommandSyntax for ApiConnectPlan {
1175    const COMMAND_BUF_SIZE: usize = 64;
1176
1177    fn append_command_syntax(&self, buf: &mut String) {
1178        buf.push_str("/_connect ");
1179        buf.push_str("plan ");
1180        write!(buf, "{}", self.user_id).unwrap();
1181        buf.push(' ');
1182        write!(
1183            buf,
1184            "{}",
1185            self.connection_link.as_deref().unwrap_or_default()
1186        )
1187        .unwrap();
1188    }
1189}
1190
1191/// ### Connection commands
1192///
1193/// 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.
1194///
1195/// ----
1196///
1197/// Connect via prepared SimpleX link. The link can be 1-time invitation link, contact address or group link
1198///
1199/// *Network usage*: interactive.
1200///
1201/// *Syntax:*
1202///
1203/// ```
1204/// /_connect <userId>[ <str(preparedLink_)>]
1205/// ```
1206#[derive(Debug, Clone, PartialEq)]
1207#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1208pub struct ApiConnect {
1209    pub user_id: i64,
1210    pub incognito: bool,
1211    pub prepared_link: Option<CreatedConnLink>,
1212}
1213
1214impl CommandSyntax for ApiConnect {
1215    const COMMAND_BUF_SIZE: usize = 256;
1216
1217    fn append_command_syntax(&self, buf: &mut String) {
1218        buf.push_str("/_connect ");
1219        write!(buf, "{}", self.user_id).unwrap();
1220        if let Some(prepared_link) = &self.prepared_link {
1221            buf.push(' ');
1222            prepared_link.append_command_syntax(buf);
1223        }
1224    }
1225}
1226
1227/// ### Connection commands
1228///
1229/// 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.
1230///
1231/// ----
1232///
1233/// Connect via SimpleX link as string in the active user profile.
1234///
1235/// *Network usage*: interactive.
1236///
1237/// *Syntax:*
1238///
1239/// ```
1240/// /connect[ <connLink_>]
1241/// ```
1242#[derive(Debug, Clone, PartialEq)]
1243#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1244pub struct Connect {
1245    pub incognito: bool,
1246    pub conn_link: Option<String>,
1247}
1248
1249impl CommandSyntax for Connect {
1250    const COMMAND_BUF_SIZE: usize = 64;
1251
1252    fn append_command_syntax(&self, buf: &mut String) {
1253        buf.push_str("/connect");
1254        if let Some(conn_link) = &self.conn_link {
1255            buf.push(' ');
1256            write!(buf, "{}", conn_link).unwrap();
1257        }
1258    }
1259}
1260
1261/// ### Connection commands
1262///
1263/// 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.
1264///
1265/// ----
1266///
1267/// Accept contact request.
1268///
1269/// *Network usage*: interactive.
1270///
1271/// *Syntax:*
1272///
1273/// ```
1274/// /_accept <contactReqId>
1275/// ```
1276#[derive(Debug, Clone, PartialEq)]
1277#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1278pub struct ApiAcceptContact {
1279    pub contact_req_id: i64,
1280}
1281
1282impl CommandSyntax for ApiAcceptContact {
1283    const COMMAND_BUF_SIZE: usize = 64;
1284
1285    fn append_command_syntax(&self, buf: &mut String) {
1286        buf.push_str("/_accept ");
1287        write!(buf, "{}", self.contact_req_id).unwrap();
1288    }
1289}
1290
1291/// ### Connection commands
1292///
1293/// 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.
1294///
1295/// ----
1296///
1297/// Reject contact request. The user who sent the request is **not notified**.
1298///
1299/// *Network usage*: no.
1300///
1301/// *Syntax:*
1302///
1303/// ```
1304/// /_reject <contactReqId>
1305/// ```
1306#[derive(Debug, Clone, PartialEq)]
1307#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1308pub struct ApiRejectContact {
1309    pub contact_req_id: i64,
1310}
1311
1312impl CommandSyntax for ApiRejectContact {
1313    const COMMAND_BUF_SIZE: usize = 64;
1314
1315    fn append_command_syntax(&self, buf: &mut String) {
1316        buf.push_str("/_reject ");
1317        write!(buf, "{}", self.contact_req_id).unwrap();
1318    }
1319}
1320
1321/// ### Chat commands
1322///
1323/// Commands to list and delete conversations.
1324///
1325/// ----
1326///
1327/// Get contacts.
1328///
1329/// *Network usage*: no.
1330///
1331/// *Syntax:*
1332///
1333/// ```
1334/// /_contacts <userId>
1335/// ```
1336#[derive(Debug, Clone, PartialEq)]
1337#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1338pub struct ApiListContacts {
1339    pub user_id: i64,
1340}
1341
1342impl CommandSyntax for ApiListContacts {
1343    const COMMAND_BUF_SIZE: usize = 64;
1344
1345    fn append_command_syntax(&self, buf: &mut String) {
1346        buf.push_str("/_contacts ");
1347        write!(buf, "{}", self.user_id).unwrap();
1348    }
1349}
1350
1351/// ### Chat commands
1352///
1353/// Commands to list and delete conversations.
1354///
1355/// ----
1356///
1357/// Get groups.
1358///
1359/// *Network usage*: no.
1360///
1361/// *Syntax:*
1362///
1363/// ```
1364/// /_groups <userId>[ @<contactId_>][ <search>]
1365/// ```
1366#[derive(Debug, Clone, PartialEq)]
1367#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1368pub struct ApiListGroups {
1369    pub user_id: i64,
1370    pub contact_id: Option<i64>,
1371    pub search: Option<String>,
1372}
1373
1374impl CommandSyntax for ApiListGroups {
1375    const COMMAND_BUF_SIZE: usize = 256;
1376
1377    fn append_command_syntax(&self, buf: &mut String) {
1378        buf.push_str("/_groups ");
1379        write!(buf, "{}", self.user_id).unwrap();
1380        if let Some(contact_id) = &self.contact_id {
1381            buf.push(' ');
1382            buf.push('@');
1383            write!(buf, "{}", contact_id).unwrap();
1384        }
1385        if let Some(search) = &self.search {
1386            buf.push(' ');
1387            write!(buf, "{}", search).unwrap();
1388        }
1389    }
1390}
1391
1392/// ### Chat commands
1393///
1394/// Commands to list and delete conversations.
1395///
1396/// ----
1397///
1398/// Delete chat.
1399///
1400/// *Network usage*: background.
1401///
1402/// *Syntax:*
1403///
1404/// ```
1405/// /_delete <str(chatRef)> <str(chatDeleteMode)>
1406/// ```
1407#[derive(Debug, Clone, PartialEq)]
1408#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1409pub struct ApiDeleteChat {
1410    pub chat_ref: ChatRef,
1411    pub chat_delete_mode: ChatDeleteMode,
1412}
1413
1414impl CommandSyntax for ApiDeleteChat {
1415    const COMMAND_BUF_SIZE: usize = 64;
1416
1417    fn append_command_syntax(&self, buf: &mut String) {
1418        buf.push_str("/_delete ");
1419        self.chat_ref.append_command_syntax(buf);
1420        buf.push(' ');
1421        self.chat_delete_mode.append_command_syntax(buf);
1422    }
1423}
1424
1425/// ### User profile commands
1426///
1427/// 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).
1428///
1429/// ----
1430///
1431/// Get active user profile
1432///
1433/// *Network usage*: no.
1434///
1435/// *Syntax:*
1436///
1437/// ```
1438/// /user
1439/// ```
1440#[derive(Debug, Clone, PartialEq)]
1441#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1442pub struct ShowActiveUser {}
1443
1444impl CommandSyntax for ShowActiveUser {
1445    const COMMAND_BUF_SIZE: usize = 0;
1446
1447    fn append_command_syntax(&self, buf: &mut String) {
1448        buf.push_str("/user");
1449    }
1450}
1451
1452/// ### User profile commands
1453///
1454/// 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).
1455///
1456/// ----
1457///
1458/// Create new user profile
1459///
1460/// *Network usage*: no.
1461///
1462/// *Syntax:*
1463///
1464/// ```
1465/// /_create user <json(newUser)>
1466/// ```
1467#[derive(Debug, Clone, PartialEq)]
1468#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1469pub struct CreateActiveUser {
1470    pub new_user: NewUser,
1471}
1472
1473impl CommandSyntax for CreateActiveUser {
1474    const COMMAND_BUF_SIZE: usize = 1024;
1475
1476    fn append_command_syntax(&self, buf: &mut String) {
1477        buf.push_str("/_create ");
1478        buf.push_str("user ");
1479        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
1480        unsafe {
1481            serde_json::to_writer(buf.as_mut_vec(), &self.new_user).unwrap();
1482        }
1483    }
1484}
1485
1486/// ### User profile commands
1487///
1488/// 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).
1489///
1490/// ----
1491///
1492/// Get all user profiles
1493///
1494/// *Network usage*: no.
1495///
1496/// *Syntax:*
1497///
1498/// ```
1499/// /users
1500/// ```
1501#[derive(Debug, Clone, PartialEq)]
1502#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1503pub struct ListUsers {}
1504
1505impl CommandSyntax for ListUsers {
1506    const COMMAND_BUF_SIZE: usize = 0;
1507
1508    fn append_command_syntax(&self, buf: &mut String) {
1509        buf.push_str("/users");
1510    }
1511}
1512
1513/// ### User profile commands
1514///
1515/// 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).
1516///
1517/// ----
1518///
1519/// Set active user profile
1520///
1521/// *Network usage*: no.
1522///
1523/// *Syntax:*
1524///
1525/// ```
1526/// /_user <userId>[ <json(viewPwd)>]
1527/// ```
1528#[derive(Debug, Clone, PartialEq)]
1529#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1530pub struct ApiSetActiveUser {
1531    pub user_id: i64,
1532    pub view_pwd: Option<String>,
1533}
1534
1535impl CommandSyntax for ApiSetActiveUser {
1536    const COMMAND_BUF_SIZE: usize = 1024;
1537
1538    fn append_command_syntax(&self, buf: &mut String) {
1539        buf.push_str("/_user ");
1540        write!(buf, "{}", self.user_id).unwrap();
1541        if let Some(view_pwd) = &self.view_pwd {
1542            buf.push(' ');
1543            // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
1544            unsafe {
1545                serde_json::to_writer(buf.as_mut_vec(), &view_pwd).unwrap();
1546            }
1547        }
1548    }
1549}
1550
1551/// ### User profile commands
1552///
1553/// 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).
1554///
1555/// ----
1556///
1557/// Delete user profile.
1558///
1559/// *Network usage*: background.
1560///
1561/// *Syntax:*
1562///
1563/// ```
1564/// /_delete user <userId> del_smp=on|off[ <json(viewPwd)>]
1565/// ```
1566#[derive(Debug, Clone, PartialEq)]
1567#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1568pub struct ApiDeleteUser {
1569    pub user_id: i64,
1570    pub del_smp_queues: bool,
1571    pub view_pwd: Option<String>,
1572}
1573
1574impl CommandSyntax for ApiDeleteUser {
1575    const COMMAND_BUF_SIZE: usize = 1024;
1576
1577    fn append_command_syntax(&self, buf: &mut String) {
1578        buf.push_str("/_delete ");
1579        buf.push_str("user ");
1580        write!(buf, "{}", self.user_id).unwrap();
1581        buf.push(' ');
1582        buf.push_str("del_smp=");
1583        if self.del_smp_queues {
1584            buf.push_str("on");
1585        } else {
1586            buf.push_str("off");
1587        }
1588        if let Some(view_pwd) = &self.view_pwd {
1589            buf.push(' ');
1590            // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
1591            unsafe {
1592                serde_json::to_writer(buf.as_mut_vec(), &view_pwd).unwrap();
1593            }
1594        }
1595    }
1596}
1597
1598/// ### User profile commands
1599///
1600/// 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).
1601///
1602/// ----
1603///
1604/// Update user profile.
1605///
1606/// *Network usage*: background.
1607///
1608/// *Syntax:*
1609///
1610/// ```
1611/// /_profile <userId> <json(profile)>
1612/// ```
1613#[derive(Debug, Clone, PartialEq)]
1614#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1615pub struct ApiUpdateProfile {
1616    pub user_id: i64,
1617    pub profile: Profile,
1618}
1619
1620impl CommandSyntax for ApiUpdateProfile {
1621    const COMMAND_BUF_SIZE: usize = 1024;
1622
1623    fn append_command_syntax(&self, buf: &mut String) {
1624        buf.push_str("/_profile ");
1625        write!(buf, "{}", self.user_id).unwrap();
1626        buf.push(' ');
1627        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
1628        unsafe {
1629            serde_json::to_writer(buf.as_mut_vec(), &self.profile).unwrap();
1630        }
1631    }
1632}
1633
1634/// ### User profile commands
1635///
1636/// 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).
1637///
1638/// ----
1639///
1640/// Configure chat preference overrides for the contact.
1641///
1642/// *Network usage*: background.
1643///
1644/// *Syntax:*
1645///
1646/// ```
1647/// /_set prefs @<contactId> <json(preferences)>
1648/// ```
1649#[derive(Debug, Clone, PartialEq)]
1650#[cfg_attr(feature = "bon", derive(::bon::Builder))]
1651pub struct ApiSetContactPrefs {
1652    pub contact_id: i64,
1653    pub preferences: Preferences,
1654}
1655
1656impl CommandSyntax for ApiSetContactPrefs {
1657    const COMMAND_BUF_SIZE: usize = 1024;
1658
1659    fn append_command_syntax(&self, buf: &mut String) {
1660        buf.push_str("/_set ");
1661        buf.push_str("prefs ");
1662        buf.push('@');
1663        write!(buf, "{}", self.contact_id).unwrap();
1664        buf.push(' ');
1665        // SAFETY: serde_json guarantees to produce valid UTF-8 sequences
1666        unsafe {
1667            serde_json::to_writer(buf.as_mut_vec(), &self.preferences).unwrap();
1668        }
1669    }
1670}