1pub const TRASH_PARENT_ID: &str = "__trash__";
8
9pub const MANAGED_PARENT_ID: &str = "__managed__";
13
14pub const ROOT_PARENT_ID: &str = "__root__";
19
20use async_trait::async_trait;
21use serde::{Deserialize, Serialize};
22use serde_with::skip_serializing_none;
23use std::{
24 cmp::Ordering,
25 collections::{HashMap, HashSet},
26 fmt::Debug,
27};
28
29use crate::{
30 prelude::*,
31 types::{serialize_timestamp_iso, serialize_timestamp_iso_opt},
32};
33
34#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
37pub enum ProfileType {
38 #[default]
39 #[serde(rename = "person")]
40 Person,
41 #[serde(rename = "community")]
42 Community,
43}
44
45#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
46pub enum ProfileStatus {
47 #[serde(rename = "A")]
48 Active,
49 #[serde(rename = "B")]
50 Blocked,
51 #[serde(rename = "M")]
52 Muted,
53 #[serde(rename = "S")]
54 Suspended,
55 #[serde(rename = "X")]
56 Banned,
57}
58
59impl ProfileStatus {
60 pub fn as_str(&self) -> &'static str {
62 match self {
63 ProfileStatus::Active => "active",
64 ProfileStatus::Blocked => "blocked",
65 ProfileStatus::Muted => "muted",
66 ProfileStatus::Suspended => "suspended",
67 ProfileStatus::Banned => "banned",
68 }
69 }
70}
71
72#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
75#[serde(rename_all = "lowercase")]
76pub enum ProfileTrust {
77 Always,
79 Never,
81}
82
83#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
84pub enum ProfileConnectionStatus {
85 #[default]
86 Disconnected,
87 RequestPending,
88 Connected,
89}
90
91impl ProfileConnectionStatus {
92 pub fn is_connected(&self) -> bool {
93 matches!(self, ProfileConnectionStatus::Connected)
94 }
95}
96
97impl std::fmt::Display for ProfileConnectionStatus {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match self {
100 ProfileConnectionStatus::Disconnected => write!(f, "disconnected"),
101 ProfileConnectionStatus::RequestPending => write!(f, "pending"),
102 ProfileConnectionStatus::Connected => write!(f, "connected"),
103 }
104 }
105}
106
107#[skip_serializing_none]
111#[derive(Debug, Clone, Serialize)]
112#[serde(rename_all = "camelCase")]
113pub struct RefData {
114 pub ref_id: Box<str>,
115 pub r#type: Box<str>,
116 pub description: Option<Box<str>>,
117 #[serde(serialize_with = "serialize_timestamp_iso")]
118 pub created_at: Timestamp,
119 #[serde(serialize_with = "serialize_timestamp_iso_opt")]
120 pub expires_at: Option<Timestamp>,
121 pub count: Option<u32>,
123 pub resource_id: Option<Box<str>>,
125 pub access_level: Option<char>,
127 pub params: Option<Box<str>>,
129}
130
131pub struct ListRefsOptions {
132 pub typ: Option<String>,
133 pub filter: Option<String>, pub resource_id: Option<String>,
136}
137
138#[derive(Default)]
139pub struct CreateRefOptions {
140 pub typ: String,
141 pub description: Option<String>,
142 pub expires_at: Option<Timestamp>,
143 pub count: Option<u32>,
144 pub resource_id: Option<String>,
146 pub access_level: Option<char>,
148 pub params: Option<String>,
150}
151
152#[derive(Debug, Default)]
158pub struct UpdateRefOptions {
159 pub description: Patch<String>,
160 pub expires_at: Patch<Timestamp>,
162 pub count: Patch<u32>,
164 pub access_level: Patch<char>,
166}
167
168#[skip_serializing_none]
169#[derive(Debug, Serialize)]
170#[serde(rename_all = "camelCase")]
171pub struct Tenant<S: AsRef<str>> {
172 #[serde(rename = "id")]
173 pub tn_id: TnId,
174 pub id_tag: S,
175 pub name: S,
176 #[serde(rename = "type")]
177 pub typ: ProfileType,
178 pub profile_pic: Option<S>,
179 pub cover_pic: Option<S>,
180 #[serde(serialize_with = "serialize_timestamp_iso")]
181 pub created_at: Timestamp,
182 pub x: HashMap<S, S>,
183}
184
185#[derive(Debug, Default)]
187pub struct ListTenantsMetaOptions {
188 pub limit: Option<u32>,
189 pub offset: Option<u32>,
190}
191
192#[skip_serializing_none]
194#[derive(Debug, Clone, Serialize)]
195#[serde(rename_all = "camelCase")]
196pub struct TenantListMeta {
197 pub tn_id: TnId,
198 pub id_tag: Box<str>,
199 pub name: Box<str>,
200 #[serde(rename = "type")]
201 pub typ: ProfileType,
202 pub profile_pic: Option<Box<str>>,
203 #[serde(serialize_with = "serialize_timestamp_iso")]
204 pub created_at: Timestamp,
205}
206
207#[derive(Debug, Default, Deserialize)]
208pub struct UpdateTenantData {
209 #[serde(rename = "idTag", default)]
210 pub id_tag: Patch<String>,
211 #[serde(default)]
212 pub name: Patch<String>,
213 #[serde(rename = "type", default)]
214 pub typ: Patch<ProfileType>,
215 #[serde(rename = "profilePic", default)]
216 pub profile_pic: Patch<String>,
217 #[serde(rename = "coverPic", default)]
218 pub cover_pic: Patch<String>,
219 #[serde(default)]
221 pub x: Option<std::collections::HashMap<String, Option<String>>>,
222}
223
224#[derive(Debug)]
225pub struct Profile<S: AsRef<str>> {
226 pub id_tag: S,
227 pub name: S,
228 pub typ: ProfileType,
229 pub profile_pic: Option<S>,
230 pub status: Option<ProfileStatus>,
231 pub synced_at: Option<Timestamp>,
232 pub following: bool,
233 pub follower: bool,
234 pub connected: ProfileConnectionStatus,
235 pub roles: Option<Box<[Box<str>]>>,
236 pub trust: Option<ProfileTrust>,
237}
238
239#[derive(Debug, Default, Deserialize)]
240pub struct ListProfileOptions {
241 #[serde(rename = "type")]
242 pub typ: Option<ProfileType>,
243 pub status: Option<Box<[ProfileStatus]>>,
244 pub connected: Option<ProfileConnectionStatus>,
245 pub following: Option<bool>,
246 pub follower: Option<bool>,
247 pub q: Option<String>,
248 pub id_tag: Option<String>,
249 pub trust_set: Option<bool>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
257#[serde(rename_all = "camelCase")]
258pub struct ProfileData {
259 pub id_tag: Box<str>,
260 pub name: Box<str>,
261 #[serde(rename = "type")]
262 pub r#type: Box<str>, pub profile_pic: Option<Box<str>>,
264 #[serde(default, skip_serializing_if = "Option::is_none")]
266 pub status: Option<Box<str>>,
267 #[serde(serialize_with = "serialize_timestamp_iso")]
268 pub created_at: Timestamp,
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct ProfileList {
274 pub profiles: Vec<ProfileData>,
275 pub total: usize,
276 pub limit: usize,
277 pub offset: usize,
278}
279
280#[derive(Debug, Default, Deserialize)]
281pub struct UpdateProfileData {
282 #[serde(default)]
284 pub name: Patch<Box<str>>,
285 #[serde(default, rename = "profilePic")]
286 pub profile_pic: Patch<Option<Box<str>>>,
287 #[serde(default)]
288 pub roles: Patch<Option<Vec<Box<str>>>>,
289
290 #[serde(default)]
292 pub status: Patch<ProfileStatus>,
293
294 #[serde(default)]
296 pub synced: Patch<bool>,
297 #[serde(default)]
298 pub trust: Patch<ProfileTrust>,
299
300 #[serde(default)]
302 pub etag: Patch<Box<str>>,
303}
304
305#[derive(Debug, Clone, Copy, PartialEq, Eq)]
307pub enum UpsertResult {
308 Created,
310 Updated,
312}
313
314#[derive(Default)]
335pub struct UpsertProfileFields {
336 pub name: Patch<Box<str>>,
337 pub typ: Patch<ProfileType>,
338 pub profile_pic: Patch<Option<Box<str>>>,
339 pub roles: Patch<Option<Vec<Box<str>>>>,
340 pub status: Patch<ProfileStatus>,
341 pub synced: Patch<bool>,
342 pub following: Patch<bool>,
343 pub follower: Patch<bool>,
344 pub connected: Patch<ProfileConnectionStatus>,
345 pub trust: Patch<ProfileTrust>,
346 pub etag: Patch<Box<str>>,
347}
348
349impl UpsertProfileFields {
350 pub fn from_update(update: UpdateProfileData) -> Self {
355 Self {
356 name: update.name,
357 typ: Patch::Undefined,
358 profile_pic: update.profile_pic,
359 roles: update.roles,
360 status: update.status,
361 synced: update.synced,
362 following: Patch::Undefined,
366 follower: Patch::Undefined,
367 connected: Patch::Undefined,
368 trust: update.trust,
369 etag: update.etag,
370 }
371 }
372}
373
374#[derive(Debug, Clone)]
379pub struct ActionData {
380 pub subject: Option<Box<str>>,
381 pub reactions: Option<Box<str>>,
382 pub comments: Option<u32>,
383 pub stat_at: Option<Timestamp>,
390}
391
392#[derive(Debug, Clone, Default)]
394pub struct UpdateActionDataOptions {
395 pub subject: Patch<String>,
396 pub reactions: Patch<String>,
397 pub comments: Patch<u32>,
398 pub comments_read: Patch<u32>,
399 pub reposts: Patch<u32>,
400 pub stat_at: Patch<Timestamp>,
402 pub status: Patch<char>,
403 pub visibility: Patch<char>,
404 pub x: Patch<serde_json::Value>, pub content: Patch<String>,
406 pub attachments: Patch<String>, pub flags: Patch<String>,
408 pub sub_typ: Patch<String>,
409 pub created_at: Patch<Timestamp>,
416}
417
418#[derive(Debug, Clone, Default)]
420pub struct FinalizeActionOptions<'a> {
421 pub attachments: Option<&'a [&'a str]>,
422 pub subject: Option<&'a str>,
423 pub audience_tag: Option<&'a str>,
424 pub key: Option<&'a str>,
425}
426
427fn deserialize_split<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
428where
429 D: serde::Deserializer<'de>,
430{
431 let s = String::deserialize(deserializer)?;
432 let values: Vec<String> =
433 s.split(',').map(|v| v.trim().to_string()).filter(|v| !v.is_empty()).collect();
434 if values.is_empty() { Ok(None) } else { Ok(Some(values)) }
435}
436
437#[derive(Debug, Clone, Copy, Deserialize)]
443#[serde(rename_all = "lowercase")]
444pub enum AudienceType {
445 Personal,
446 Community,
447}
448
449#[derive(Debug, Clone, Copy)]
452pub enum ActionCountGroupBy {
453 SubType,
454}
455
456#[derive(Debug, Default, Deserialize)]
458#[serde(deny_unknown_fields)]
459pub struct ListActionOptions {
460 pub limit: Option<u32>,
462 pub cursor: Option<String>,
464 pub sort: Option<String>,
466 #[serde(rename = "sortDir")]
468 pub sort_dir: Option<String>,
469 #[serde(default, rename = "type", deserialize_with = "deserialize_split")]
470 pub typ: Option<Vec<String>>,
471 #[serde(default, deserialize_with = "deserialize_split")]
472 pub status: Option<Vec<String>>,
473 pub tag: Option<String>,
474 pub search: Option<String>,
475 #[serde(default, deserialize_with = "deserialize_split")]
476 pub visibility: Option<Vec<String>>,
477 pub issuer: Option<String>,
478 pub audience: Option<String>,
479 #[serde(rename = "audienceType")]
480 pub audience_type: Option<AudienceType>,
481 pub involved: Option<String>,
482 #[serde(skip)]
484 pub viewer_id_tag: Option<String>,
485 #[serde(rename = "actionId")]
486 pub action_id: Option<String>,
487 #[serde(rename = "parentId")]
488 pub parent_id: Option<String>,
489 #[serde(rename = "rootId")]
490 pub root_id: Option<String>,
491 pub subject: Option<String>,
492 #[serde(rename = "createdAfter")]
493 pub created_after: Option<Timestamp>,
494 #[serde(rename = "includeTokens")]
497 pub include_tokens: Option<bool>,
498 #[serde(skip)]
502 pub exclude_issuer_profile_status: Option<Box<[ProfileStatus]>>,
503 #[serde(skip)]
508 pub exclude_sub_typ: Option<Box<[Box<str>]>>,
509}
510
511#[skip_serializing_none]
512#[derive(Debug, Clone, Serialize, serde::Deserialize)]
513pub struct ProfileInfo {
514 #[serde(rename = "idTag")]
515 pub id_tag: Box<str>,
516 pub name: Box<str>,
517 #[serde(rename = "type")]
518 pub typ: ProfileType,
519 #[serde(rename = "profilePic")]
520 pub profile_pic: Option<Box<str>>,
521}
522
523#[derive(Default)]
524pub struct Action<S: AsRef<str>> {
525 pub action_id: S,
526 pub typ: S,
527 pub sub_typ: Option<S>,
528 pub issuer_tag: S,
529 pub parent_id: Option<S>,
530 pub root_id: Option<S>,
531 pub audience_tag: Option<S>,
532 pub content: Option<S>,
533 pub attachments: Option<Vec<S>>,
534 pub subject: Option<S>,
535 pub created_at: Timestamp,
536 pub expires_at: Option<Timestamp>,
537 pub visibility: Option<char>, pub flags: Option<S>, pub x: Option<serde_json::Value>, }
541
542#[skip_serializing_none]
543#[derive(Debug, Clone, Serialize)]
544pub struct AttachmentView {
545 #[serde(rename = "fileId")]
546 pub file_id: Box<str>,
547 pub dim: Option<(u32, u32)>,
548 #[serde(rename = "localVariants")]
549 pub local_variants: Option<Vec<Box<str>>>,
550}
551
552#[skip_serializing_none]
553#[derive(Debug, Clone, Serialize)]
554#[serde(rename_all = "camelCase")]
555pub struct ActionView {
556 pub action_id: Box<str>,
557 #[serde(rename = "type")]
558 pub typ: Box<str>,
559 #[serde(rename = "subType")]
560 pub sub_typ: Option<Box<str>>,
561 pub parent_id: Option<Box<str>>,
562 pub root_id: Option<Box<str>>,
563 pub issuer: ProfileInfo,
564 pub audience: Option<ProfileInfo>,
565 pub content: Option<serde_json::Value>,
566 pub attachments: Option<Vec<AttachmentView>>,
567 pub subject: Option<Box<str>>,
568 pub subject_profile: Option<ProfileInfo>,
569 #[serde(default, skip_serializing_if = "Option::is_none")]
574 pub subject_action: Option<Box<ActionView>>,
575 #[serde(serialize_with = "serialize_timestamp_iso")]
576 pub created_at: Timestamp,
577 #[serde(serialize_with = "serialize_timestamp_iso_opt")]
578 pub expires_at: Option<Timestamp>,
579 pub status: Option<Box<str>>,
580 pub stat: Option<serde_json::Value>,
581 pub visibility: Option<char>,
582 pub flags: Option<Box<str>>, pub x: Option<serde_json::Value>, #[serde(default, skip_serializing_if = "Option::is_none")]
587 pub token: Option<Box<str>>,
588}
589
590#[derive(Debug)]
593pub enum FileId<S: AsRef<str>> {
594 FileId(S),
595 FId(u64),
596}
597
598pub enum ActionId<S: AsRef<str>> {
599 ActionId(S),
600 AId(u64),
601}
602
603#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
606pub enum FileStatus {
607 #[serde(rename = "A")]
608 Active,
609 #[serde(rename = "P")]
610 Pending,
611 #[serde(rename = "D")]
612 Deleted,
613}
614
615#[skip_serializing_none]
617#[derive(Debug, Clone, Default, Serialize, serde::Deserialize)]
618#[serde(rename_all = "camelCase")]
619pub struct FileUserData {
620 #[serde(default, serialize_with = "serialize_timestamp_iso_opt")]
621 pub accessed_at: Option<Timestamp>,
622 #[serde(default, serialize_with = "serialize_timestamp_iso_opt")]
623 pub modified_at: Option<Timestamp>,
624 #[serde(default)]
625 pub pinned: bool,
626 #[serde(default)]
627 pub starred: bool,
628 #[serde(default)]
634 pub access_level: Option<crate::types::AccessLevel>,
635}
636
637#[skip_serializing_none]
638#[derive(Debug, Clone, Serialize, serde::Deserialize)]
639#[serde(rename_all = "camelCase")]
640pub struct FileView {
641 pub file_id: Box<str>,
642 #[serde(default)]
643 pub parent_id: Option<Box<str>>, #[serde(default)]
645 pub root_id: Option<Box<str>>, #[serde(default)]
647 pub owner: Option<ProfileInfo>,
648 #[serde(default)]
649 pub creator: Option<ProfileInfo>,
650 #[serde(default)]
651 pub preset: Option<Box<str>>,
652 #[serde(default)]
653 pub content_type: Option<Box<str>>,
654 pub file_name: Box<str>,
655 #[serde(default)]
656 pub file_tp: Option<Box<str>>, #[serde(serialize_with = "serialize_timestamp_iso")]
658 pub created_at: Timestamp,
659 #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
660 pub accessed_at: Option<Timestamp>, #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
662 pub modified_at: Option<Timestamp>, pub status: FileStatus,
664 #[serde(default)]
665 pub tags: Option<Vec<Box<str>>>,
666 #[serde(default)]
667 pub visibility: Option<char>, #[serde(default)]
673 pub hidden: bool,
674 #[serde(default)]
675 pub access_level: Option<crate::types::AccessLevel>, #[serde(default)]
677 pub user_data: Option<FileUserData>, #[serde(default)]
679 pub x: Option<serde_json::Value>, #[serde(default)]
684 pub parent_name: Option<Box<str>>,
685 #[serde(default)]
689 pub path: Option<Vec<PathSegment>>,
690 #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
697 pub broken_at: Option<Timestamp>,
698 #[serde(default)]
701 pub broken_reason: Option<BrokenReason>,
702}
703
704#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
710#[serde(rename_all = "lowercase")]
711pub enum BrokenReason {
712 Deleted,
714 Revoked,
716}
717
718impl BrokenReason {
719 pub fn as_str(&self) -> &'static str {
720 match self {
721 Self::Deleted => "deleted",
722 Self::Revoked => "revoked",
723 }
724 }
725}
726
727#[derive(Debug, Clone, Serialize, serde::Deserialize)]
729#[serde(rename_all = "camelCase")]
730pub struct PathSegment {
731 pub id: Box<str>,
732 pub name: Box<str>,
733}
734
735#[skip_serializing_none]
736#[derive(Debug, Clone, Serialize)]
737pub struct FileVariant<S: AsRef<str> + Debug> {
738 #[serde(rename = "variantId")]
739 pub variant_id: S,
740 pub variant: S,
741 pub format: S,
742 pub size: u64,
743 pub resolution: (u32, u32),
744 pub available: bool,
745 #[serde(skip_serializing_if = "std::ops::Not::not")]
747 pub global: bool,
748 pub duration: Option<f64>,
750 pub bitrate: Option<u32>,
752 #[serde(rename = "pageCount")]
754 pub page_count: Option<u32>,
755}
756
757impl<S: AsRef<str> + Debug> PartialEq for FileVariant<S> {
760 fn eq(&self, other: &Self) -> bool {
761 self.variant_id.as_ref() == other.variant_id.as_ref()
762 && self.variant.as_ref() == other.variant.as_ref()
763 && self.format.as_ref() == other.format.as_ref()
764 && self.size == other.size
765 && self.resolution == other.resolution
766 && self.available == other.available
767 && self.duration == other.duration
768 && self.bitrate == other.bitrate
769 && self.page_count == other.page_count
770 }
771}
772
773impl<S: AsRef<str> + Debug> Eq for FileVariant<S> {}
774
775impl<S: AsRef<str> + Debug + Ord> PartialOrd for FileVariant<S> {
776 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
777 Some(self.cmp(other))
778 }
779}
780
781impl<S: AsRef<str> + Debug + Ord> Ord for FileVariant<S> {
782 fn cmp(&self, other: &Self) -> Ordering {
783 self.size
784 .cmp(&other.size)
785 .then_with(|| self.resolution.0.cmp(&other.resolution.0))
786 .then_with(|| self.resolution.1.cmp(&other.resolution.1))
787 .then_with(|| self.variant.as_ref().cmp(other.variant.as_ref()))
788 }
789}
790
791#[derive(Debug, Default, Deserialize)]
796#[serde(deny_unknown_fields)]
797pub struct ListFileOptions {
798 pub limit: Option<u32>,
800 pub cursor: Option<String>,
802 #[serde(default, rename = "fileId", deserialize_with = "deserialize_split")]
803 pub file_id: Option<Vec<String>>,
804 #[serde(rename = "parentId")]
805 pub parent_id: Option<String>, #[serde(rename = "notParentId")]
810 pub not_parent_id: Option<String>,
811 #[serde(rename = "rootId")]
812 pub root_id: Option<String>, pub tag: Option<String>,
814 pub preset: Option<String>,
815 pub variant: Option<String>,
816 pub status: Option<FileStatus>,
818 #[serde(default, rename = "fileTp", deserialize_with = "deserialize_split")]
819 pub file_type: Option<Vec<String>>,
820 #[serde(default, rename = "contentType", deserialize_with = "deserialize_split")]
822 pub content_type: Option<Vec<String>>,
823 #[serde(rename = "fileName")]
825 pub file_name: Option<String>,
826 #[serde(rename = "ownerIdTag")]
828 pub owner_id_tag: Option<String>,
829 #[serde(rename = "notOwnerIdTag")]
831 pub not_owner_id_tag: Option<String>,
832 pub pinned: Option<bool>,
834 pub starred: Option<bool>,
836 pub hidden: Option<bool>,
841 pub sort: Option<String>,
843 #[serde(rename = "sortDir")]
845 pub sort_dir: Option<String>,
846 #[serde(skip)]
848 pub user_id_tag: Option<String>,
849 #[serde(skip)]
852 pub scope_file_id: Option<String>,
853 #[serde(skip)]
857 pub visible_levels: Option<Vec<char>>,
858 #[serde(default, rename = "withParent")]
862 pub with_parent: bool,
863 #[serde(default, rename = "withPath")]
866 pub with_path: bool,
867}
868
869#[derive(Debug, Clone, Default)]
870pub struct CreateFile {
871 pub orig_variant_id: Option<Box<str>>,
872 pub file_id: Option<Box<str>>,
873 pub parent_id: Option<Box<str>>, pub root_id: Option<Box<str>>, pub owner_tag: Option<Box<str>>, pub creator_tag: Option<Box<str>>, pub preset: Option<Box<str>>,
878 pub content_type: Box<str>,
879 pub file_name: Box<str>,
880 pub file_tp: Option<Box<str>>, pub created_at: Option<Timestamp>,
882 pub tags: Option<Vec<Box<str>>>,
883 pub x: Option<serde_json::Value>,
884 pub visibility: Option<char>, pub hidden: bool,
888 pub status: Option<FileStatus>, }
890
891#[derive(Debug, Clone, Deserialize)]
892pub struct CreateFileVariant {
893 pub variant: Box<str>,
894 pub format: Box<str>,
895 pub resolution: (u32, u32),
896 pub size: u64,
897 pub available: bool,
898}
899
900#[derive(Debug, Clone, Default, Deserialize)]
902pub struct UpdateFileOptions {
903 #[serde(default, rename = "fileName")]
904 pub file_name: Patch<String>,
905 #[serde(default, rename = "parentId")]
906 pub parent_id: Patch<String>, #[serde(default)]
908 pub visibility: Patch<char>,
909 #[serde(default)]
910 pub status: Patch<char>,
911 #[serde(default)]
914 pub hidden: Patch<bool>,
915 #[serde(default, rename = "contentType", skip_deserializing)]
918 pub content_type: Patch<String>,
919 #[serde(default, rename = "fileTp", skip_deserializing)]
920 pub file_tp: Patch<String>,
921 #[serde(default, skip_deserializing)]
922 pub tags: Patch<Vec<String>>,
923 #[serde(default, skip_deserializing)]
924 pub preset: Patch<String>,
925 #[serde(default, skip_deserializing)]
926 pub x: Patch<serde_json::Value>,
927 #[serde(default, skip_deserializing)]
931 pub broken: Patch<BrokenReason>,
932}
933
934#[skip_serializing_none]
938#[derive(Debug, Clone, Serialize)]
939#[serde(rename_all = "camelCase")]
940pub struct ShareEntry {
941 pub id: i64,
942 pub resource_type: char,
943 pub resource_id: Box<str>,
944 pub subject_type: char,
945 pub subject_id: Box<str>,
946 pub permission: char,
947 #[serde(serialize_with = "serialize_timestamp_iso_opt")]
948 pub expires_at: Option<Timestamp>,
949 pub created_by: Box<str>,
950 #[serde(serialize_with = "serialize_timestamp_iso")]
951 pub created_at: Timestamp,
952 pub subject_file_name: Option<Box<str>>,
954 pub subject_content_type: Option<Box<str>>,
955 pub subject_file_tp: Option<Box<str>>,
956}
957
958#[derive(Debug, Deserialize)]
959#[serde(rename_all = "camelCase")]
960pub struct CreateShareEntry {
961 pub subject_type: char,
962 pub subject_id: String,
963 pub permission: char,
964 pub expires_at: Option<Timestamp>,
965}
966
967#[derive(Debug, Default)]
974pub struct UpdateShareEntryOptions {
975 pub permission: Patch<char>,
978 pub expires_at: Patch<Timestamp>,
980}
981
982#[skip_serializing_none]
987#[derive(Debug, Clone, Serialize, Deserialize)]
988pub struct PushSubscriptionData {
989 pub endpoint: String,
991 #[serde(rename = "expirationTime")]
993 pub expiration_time: Option<i64>,
994 pub keys: PushSubscriptionKeys,
996}
997
998#[derive(Debug, Clone, Serialize, Deserialize)]
1000pub struct PushSubscriptionKeys {
1001 pub p256dh: String,
1003 pub auth: String,
1005}
1006
1007#[derive(Debug, Clone, Serialize)]
1009#[serde(rename_all = "camelCase")]
1010pub struct PushSubscription {
1011 pub id: u64,
1013 pub subscription: PushSubscriptionData,
1015 #[serde(serialize_with = "serialize_timestamp_iso")]
1017 pub created_at: Timestamp,
1018}
1019
1020pub struct Task {
1023 pub task_id: u64,
1024 pub tn_id: TnId,
1025 pub kind: Box<str>,
1026 pub status: char,
1027 pub created_at: Timestamp,
1028 pub next_at: Option<Timestamp>,
1029 pub input: Box<str>,
1030 pub output: Box<str>,
1031 pub deps: Box<[u64]>,
1032 pub retry: Option<Box<str>>,
1033 pub cron: Option<Box<str>>,
1034}
1035
1036#[derive(Debug, Default)]
1037pub struct TaskPatch {
1038 pub input: Patch<String>,
1039 pub next_at: Patch<Timestamp>,
1040 pub deps: Patch<Vec<u64>>,
1041 pub retry: Patch<String>,
1042 pub cron: Patch<String>,
1043}
1044
1045#[derive(Debug, Default)]
1046pub struct ListTaskOptions {}
1047
1048#[derive(Debug)]
1053pub struct InstallApp {
1054 pub app_name: Box<str>,
1055 pub publisher_tag: Box<str>,
1056 pub version: Box<str>,
1057 pub action_id: Box<str>,
1058 pub file_id: Box<str>,
1059 pub blob_id: Box<str>,
1060 pub capabilities: Option<Vec<Box<str>>>,
1061}
1062
1063#[derive(Debug, Serialize)]
1065#[serde(rename_all = "camelCase")]
1066pub struct InstalledApp {
1067 pub app_name: Box<str>,
1068 pub publisher_tag: Box<str>,
1069 pub version: Box<str>,
1070 pub action_id: Box<str>,
1071 pub file_id: Box<str>,
1072 pub blob_id: Box<str>,
1073 pub status: Box<str>,
1074 pub capabilities: Option<Vec<Box<str>>>,
1075 pub auto_update: bool,
1076 #[serde(serialize_with = "serialize_timestamp_iso")]
1077 pub installed_at: Timestamp,
1078}
1079
1080#[derive(Debug, Clone, Serialize)]
1085#[serde(rename_all = "camelCase")]
1086pub struct AddressBook {
1087 pub ab_id: u64,
1088 pub name: Box<str>,
1089 pub description: Option<Box<str>>,
1090 pub ctag: Box<str>,
1092 #[serde(serialize_with = "serialize_timestamp_iso")]
1093 pub created_at: Timestamp,
1094 #[serde(serialize_with = "serialize_timestamp_iso")]
1095 pub updated_at: Timestamp,
1096}
1097
1098#[derive(Debug, Default)]
1099pub struct UpdateAddressBookData {
1100 pub name: Patch<String>,
1101 pub description: Patch<String>,
1102}
1103
1104#[derive(Debug, Clone, Default)]
1108pub struct ContactExtracted {
1109 pub fn_name: Option<Box<str>>,
1110 pub given_name: Option<Box<str>>,
1111 pub family_name: Option<Box<str>>,
1112 pub email: Option<Box<str>>,
1113 pub emails: Option<Box<str>>,
1114 pub tel: Option<Box<str>>,
1115 pub tels: Option<Box<str>>,
1116 pub org: Option<Box<str>>,
1117 pub title: Option<Box<str>>,
1118 pub note: Option<Box<str>>,
1119 pub photo_uri: Option<Box<str>>,
1120 pub profile_id_tag: Option<Box<str>>,
1121}
1122
1123#[derive(Debug, Clone)]
1125pub struct Contact {
1126 pub c_id: u64,
1127 pub ab_id: u64,
1128 pub uid: Box<str>,
1129 pub etag: Box<str>,
1130 pub vcard: Box<str>,
1131 pub extracted: ContactExtracted,
1132 pub created_at: Timestamp,
1133 pub updated_at: Timestamp,
1134}
1135
1136#[derive(Debug, Clone)]
1139pub struct ContactView {
1140 pub c_id: u64,
1141 pub ab_id: u64,
1142 pub uid: Box<str>,
1143 pub etag: Box<str>,
1144 pub extracted: ContactExtracted,
1145 pub created_at: Timestamp,
1146 pub updated_at: Timestamp,
1147}
1148
1149#[derive(Debug, Clone)]
1152pub struct ContactSyncEntry {
1153 pub uid: Box<str>,
1154 pub etag: Box<str>,
1155 pub deleted: bool,
1156 pub updated_at: Timestamp,
1157}
1158
1159#[derive(Debug, Default)]
1160pub struct ListContactOptions {
1161 pub q: Option<String>,
1163 pub cursor: Option<String>,
1165 pub limit: Option<u32>,
1167}
1168
1169#[derive(Debug, Clone, Serialize)]
1174#[serde(rename_all = "camelCase")]
1175pub struct Calendar {
1176 pub cal_id: u64,
1177 pub name: Box<str>,
1178 pub description: Option<Box<str>>,
1179 pub color: Option<Box<str>>,
1181 pub timezone: Option<Box<str>>,
1183 pub components: Box<str>,
1185 pub ctag: Box<str>,
1187 #[serde(serialize_with = "serialize_timestamp_iso")]
1188 pub created_at: Timestamp,
1189 #[serde(serialize_with = "serialize_timestamp_iso")]
1190 pub updated_at: Timestamp,
1191}
1192
1193#[derive(Debug, Default)]
1194pub struct CreateCalendarData {
1195 pub name: String,
1196 pub description: Option<String>,
1197 pub color: Option<String>,
1198 pub timezone: Option<String>,
1199 pub components: Option<String>,
1201}
1202
1203#[derive(Debug, Default)]
1204pub struct UpdateCalendarData {
1205 pub name: Patch<String>,
1206 pub description: Patch<String>,
1207 pub color: Patch<String>,
1208 pub timezone: Patch<String>,
1209 pub components: Patch<String>,
1210}
1211
1212#[derive(Debug, Clone, Default)]
1215pub struct CalendarObjectExtracted {
1216 pub component: Box<str>,
1218 pub summary: Option<Box<str>>,
1219 pub location: Option<Box<str>>,
1220 pub description: Option<Box<str>>,
1221 pub dtstart: Option<Timestamp>,
1223 pub dtend: Option<Timestamp>,
1225 pub all_day: bool,
1227 pub status: Option<Box<str>>,
1229 pub priority: Option<u8>,
1231 pub organizer: Option<Box<str>>,
1232 pub rrule: Option<Box<str>>,
1234 pub exdate: Vec<Timestamp>,
1236 pub recurrence_id: Option<Timestamp>,
1238 pub sequence: i64,
1239}
1240
1241#[derive(Debug, Clone, Copy)]
1246pub struct CalendarObjectWrite<'a> {
1247 pub uid: &'a str,
1248 pub ical: &'a str,
1249 pub etag: &'a str,
1250 pub extracted: &'a CalendarObjectExtracted,
1251}
1252
1253#[derive(Debug, Clone)]
1255pub struct CalendarObject {
1256 pub co_id: u64,
1257 pub cal_id: u64,
1258 pub uid: Box<str>,
1259 pub etag: Box<str>,
1260 pub ical: Box<str>,
1261 pub extracted: CalendarObjectExtracted,
1262 pub created_at: Timestamp,
1263 pub updated_at: Timestamp,
1264}
1265
1266#[derive(Debug, Clone)]
1268pub struct CalendarObjectView {
1269 pub co_id: u64,
1270 pub cal_id: u64,
1271 pub uid: Box<str>,
1272 pub etag: Box<str>,
1273 pub extracted: CalendarObjectExtracted,
1274 pub created_at: Timestamp,
1275 pub updated_at: Timestamp,
1276}
1277
1278#[derive(Debug, Clone)]
1281pub struct CalendarObjectSyncEntry {
1282 pub uid: Box<str>,
1283 pub etag: Box<str>,
1284 pub deleted: bool,
1285 pub updated_at: Timestamp,
1286}
1287
1288#[derive(Debug, Default)]
1289pub struct ListCalendarObjectOptions {
1290 pub component: Option<String>,
1292 pub q: Option<String>,
1294 pub start: Option<Timestamp>,
1296 pub end: Option<Timestamp>,
1298 pub cursor: Option<String>,
1299 pub limit: Option<u32>,
1300 pub include_exceptions: bool,
1303}
1304
1305#[async_trait]
1306pub trait MetaAdapter: Debug + Send + Sync {
1307 async fn read_tenant(&self, tn_id: TnId) -> ClResult<Tenant<Box<str>>>;
1312
1313 async fn create_tenant(&self, tn_id: TnId, id_tag: &str) -> ClResult<TnId>;
1315
1316 async fn update_tenant(&self, tn_id: TnId, tenant: &UpdateTenantData) -> ClResult<()>;
1318
1319 async fn delete_tenant(&self, tn_id: TnId) -> ClResult<()>;
1321
1322 async fn list_tenants(&self, opts: &ListTenantsMetaOptions) -> ClResult<Vec<TenantListMeta>>;
1324
1325 async fn list_profiles(
1327 &self,
1328 tn_id: TnId,
1329 opts: &ListProfileOptions,
1330 ) -> ClResult<Vec<Profile<Box<str>>>>;
1331
1332 async fn list_follower_tags(&self, tn_id: TnId) -> ClResult<Vec<Box<str>>>;
1337
1338 async fn get_relationships(
1345 &self,
1346 tn_id: TnId,
1347 target_id_tags: &[&str],
1348 ) -> ClResult<HashMap<String, (bool, bool)>>;
1349
1350 async fn read_profile(
1354 &self,
1355 tn_id: TnId,
1356 id_tag: &str,
1357 ) -> ClResult<(Box<str>, Profile<Box<str>>)>;
1358
1359 async fn read_profile_roles(
1361 &self,
1362 tn_id: TnId,
1363 id_tag: &str,
1364 ) -> ClResult<Option<Box<[Box<str>]>>>;
1365
1366 async fn upsert_profile(
1373 &self,
1374 tn_id: TnId,
1375 id_tag: &str,
1376 fields: &UpsertProfileFields,
1377 ) -> ClResult<UpsertResult>;
1378
1379 async fn read_profile_public_key(
1383 &self,
1384 id_tag: &str,
1385 key_id: &str,
1386 ) -> ClResult<(Box<str>, Timestamp)>;
1387 async fn add_profile_public_key(
1393 &self,
1394 id_tag: &str,
1395 key_id: &str,
1396 public_key: &str,
1397 expires_at: Option<Timestamp>,
1398 ) -> ClResult<()>;
1399 async fn list_stale_profiles(
1410 &self,
1411 max_age_secs: i64,
1412 disable_after_secs: i64,
1413 limit: u32,
1414 ) -> ClResult<Vec<(TnId, Box<str>, Option<Box<str>>)>>;
1415
1416 async fn get_action_id(&self, tn_id: TnId, a_id: u64) -> ClResult<Box<str>>;
1419 async fn list_actions(
1420 &self,
1421 tn_id: TnId,
1422 opts: &ListActionOptions,
1423 ) -> ClResult<Vec<ActionView>>;
1424 async fn list_action_tokens(
1425 &self,
1426 tn_id: TnId,
1427 opts: &ListActionOptions,
1428 ) -> ClResult<Box<[Box<str>]>>;
1429
1430 async fn count_actions(&self, tn_id: TnId, opts: &ListActionOptions) -> ClResult<i64>;
1434
1435 async fn count_actions_grouped(
1439 &self,
1440 tn_id: TnId,
1441 opts: &ListActionOptions,
1442 group_by: ActionCountGroupBy,
1443 ) -> ClResult<Vec<(Option<String>, i64)>>;
1444
1445 async fn create_action(
1446 &self,
1447 tn_id: TnId,
1448 action: &Action<&str>,
1449 key: Option<&str>,
1450 ) -> ClResult<ActionId<Box<str>>>;
1451
1452 async fn finalize_action(
1453 &self,
1454 tn_id: TnId,
1455 a_id: u64,
1456 action_id: &str,
1457 options: FinalizeActionOptions<'_>,
1458 ) -> ClResult<()>;
1459
1460 async fn create_inbound_action(
1461 &self,
1462 tn_id: TnId,
1463 action_id: &str,
1464 token: &str,
1465 ack_token: Option<&str>,
1466 ) -> ClResult<()>;
1467
1468 async fn get_action_root_id(&self, tn_id: TnId, action_id: &str) -> ClResult<Box<str>>;
1470
1471 async fn get_action_data(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<ActionData>>;
1473
1474 async fn get_action_by_key(
1476 &self,
1477 tn_id: TnId,
1478 action_key: &str,
1479 ) -> ClResult<Option<Action<Box<str>>>>;
1480
1481 async fn store_action_token(&self, tn_id: TnId, action_id: &str, token: &str) -> ClResult<()>;
1483
1484 async fn get_action_token(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<Box<str>>>;
1486
1487 async fn update_action_data(
1489 &self,
1490 tn_id: TnId,
1491 action_id: &str,
1492 opts: &UpdateActionDataOptions,
1493 ) -> ClResult<()>;
1494
1495 async fn update_inbound_action(
1497 &self,
1498 tn_id: TnId,
1499 action_id: &str,
1500 status: Option<char>,
1501 ) -> ClResult<()>;
1502
1503 async fn get_related_action_tokens(
1506 &self,
1507 tn_id: TnId,
1508 aprv_action_id: &str,
1509 ) -> ClResult<Vec<(Box<str>, Box<str>)>>;
1510
1511 async fn get_file_id(&self, tn_id: TnId, f_id: u64) -> ClResult<Box<str>>;
1514 async fn list_files(&self, tn_id: TnId, opts: &ListFileOptions) -> ClResult<Vec<FileView>>;
1515 async fn list_file_variants(
1516 &self,
1517 tn_id: TnId,
1518 file_id: FileId<&str>,
1519 ) -> ClResult<Vec<FileVariant<Box<str>>>>;
1520 async fn list_available_variants(&self, tn_id: TnId, file_id: &str) -> ClResult<Vec<Box<str>>>;
1522 async fn list_referenced_variant_ids(&self, tn_id: TnId) -> ClResult<Vec<Box<str>>>;
1527 async fn is_variant_referenced(&self, tn_id: TnId, variant_id: &str) -> ClResult<bool>;
1533 async fn read_file_variant(
1534 &self,
1535 tn_id: TnId,
1536 variant_id: &str,
1537 ) -> ClResult<FileVariant<Box<str>>>;
1538 async fn read_file_id_by_variant(&self, tn_id: TnId, variant_id: &str) -> ClResult<Box<str>>;
1540 async fn read_f_id_by_file_id(&self, tn_id: TnId, file_id: &str) -> ClResult<u64>;
1542 async fn create_file(&self, tn_id: TnId, opts: CreateFile) -> ClResult<FileId<Box<str>>>;
1543 async fn create_file_variant<'a>(
1544 &'a self,
1545 tn_id: TnId,
1546 f_id: u64,
1547 opts: FileVariant<&'a str>,
1548 ) -> ClResult<&'a str>;
1549 async fn update_file_id(&self, tn_id: TnId, f_id: u64, file_id: &str) -> ClResult<()>;
1550
1551 async fn finalize_file(&self, tn_id: TnId, f_id: u64, file_id: &str) -> ClResult<()>;
1553
1554 async fn list_files_by_parent(
1559 &self,
1560 tn_id: TnId,
1561 parent_id: &str,
1562 before: Timestamp,
1563 ) -> ClResult<Vec<u64>>;
1564
1565 async fn list_referenced_managed_fids(&self, tn_id: TnId) -> ClResult<HashSet<u64>>;
1587
1588 async fn hard_delete_file(&self, tn_id: TnId, f_id: u64) -> ClResult<()>;
1591
1592 async fn list_tasks(&self, opts: ListTaskOptions) -> ClResult<Vec<Task>>;
1595 async fn list_task_ids(&self, kind: &str, keys: &[Box<str>]) -> ClResult<Vec<u64>>;
1596 async fn create_task(
1597 &self,
1598 kind: &'static str,
1599 key: Option<&str>,
1600 input: &str,
1601 deps: &[u64],
1602 ) -> ClResult<u64>;
1603 async fn update_task_finished(&self, task_id: u64, output: &str) -> ClResult<()>;
1604 async fn update_task_error(
1605 &self,
1606 task_id: u64,
1607 output: &str,
1608 next_at: Option<Timestamp>,
1609 ) -> ClResult<()>;
1610
1611 async fn find_task_by_key(&self, key: &str) -> ClResult<Option<Task>>;
1613
1614 async fn update_task(&self, task_id: u64, patch: &TaskPatch) -> ClResult<()>;
1616
1617 async fn find_completed_deps(&self, deps: &[u64]) -> ClResult<Vec<u64>>;
1619
1620 async fn get_profile_info(&self, tn_id: TnId, id_tag: &str) -> ClResult<ProfileData>;
1624
1625 async fn get_action(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<ActionView>>;
1629
1630 async fn update_action(
1632 &self,
1633 tn_id: TnId,
1634 action_id: &str,
1635 content: Option<&str>,
1636 attachments: Option<&[&str]>,
1637 ) -> ClResult<()>;
1638
1639 async fn delete_action(&self, tn_id: TnId, action_id: &str) -> ClResult<()>;
1641
1642 async fn delete_file(&self, tn_id: TnId, file_id: &str) -> ClResult<()>;
1646
1647 async fn list_children_by_root(&self, tn_id: TnId, root_id: &str) -> ClResult<Vec<Box<str>>>;
1649
1650 async fn list_settings(
1654 &self,
1655 tn_id: TnId,
1656 prefix: Option<&[String]>,
1657 ) -> ClResult<std::collections::HashMap<String, serde_json::Value>>;
1658
1659 async fn read_setting(&self, tn_id: TnId, name: &str) -> ClResult<Option<serde_json::Value>>;
1661
1662 async fn update_setting(
1664 &self,
1665 tn_id: TnId,
1666 name: &str,
1667 value: Option<serde_json::Value>,
1668 ) -> ClResult<()>;
1669
1670 async fn list_refs(&self, tn_id: TnId, opts: &ListRefsOptions) -> ClResult<Vec<RefData>>;
1674
1675 async fn get_ref(&self, tn_id: TnId, ref_id: &str) -> ClResult<Option<RefData>>;
1677
1678 async fn create_ref(
1680 &self,
1681 tn_id: TnId,
1682 ref_id: &str,
1683 opts: &CreateRefOptions,
1684 ) -> ClResult<RefData>;
1685
1686 async fn delete_ref(&self, tn_id: TnId, ref_id: &str) -> ClResult<()>;
1688
1689 async fn update_ref(
1691 &self,
1692 tn_id: TnId,
1693 ref_id: &str,
1694 opts: &UpdateRefOptions,
1695 ) -> ClResult<RefData>;
1696
1697 async fn use_ref(
1700 &self,
1701 ref_id: &str,
1702 expected_types: &[&str],
1703 ) -> ClResult<(TnId, Box<str>, RefData)>;
1704
1705 async fn validate_ref(
1708 &self,
1709 ref_id: &str,
1710 expected_types: &[&str],
1711 ) -> ClResult<(TnId, Box<str>, RefData)>;
1712
1713 async fn list_tags(
1723 &self,
1724 tn_id: TnId,
1725 prefix: Option<&str>,
1726 with_counts: bool,
1727 limit: Option<u32>,
1728 ) -> ClResult<Vec<TagInfo>>;
1729
1730 async fn add_tag(&self, tn_id: TnId, file_id: &str, tag: &str) -> ClResult<Vec<String>>;
1732
1733 async fn remove_tag(&self, tn_id: TnId, file_id: &str, tag: &str) -> ClResult<Vec<String>>;
1735
1736 async fn update_file_data(
1740 &self,
1741 tn_id: TnId,
1742 file_id: &str,
1743 opts: &UpdateFileOptions,
1744 ) -> ClResult<()>;
1745
1746 async fn read_file(&self, tn_id: TnId, file_id: &str) -> ClResult<Option<FileView>>;
1748
1749 async fn read_file_with_user_data(
1753 &self,
1754 tn_id: TnId,
1755 file_id: &str,
1756 id_tag: &str,
1757 ) -> ClResult<Option<FileView>>;
1758
1759 async fn record_file_access(&self, tn_id: TnId, id_tag: &str, file_id: &str) -> ClResult<()>;
1764
1765 async fn record_file_modification(
1767 &self,
1768 tn_id: TnId,
1769 id_tag: &str,
1770 file_id: &str,
1771 ) -> ClResult<()>;
1772
1773 async fn update_file_user_data(
1782 &self,
1783 tn_id: TnId,
1784 id_tag: &str,
1785 file_id: &str,
1786 pinned: crate::types::Patch<bool>,
1787 starred: crate::types::Patch<bool>,
1788 access_level: crate::types::Patch<char>,
1789 ) -> ClResult<FileUserData>;
1790
1791 async fn get_file_user_data(
1793 &self,
1794 tn_id: TnId,
1795 id_tag: &str,
1796 file_id: &str,
1797 ) -> ClResult<Option<FileUserData>>;
1798
1799 async fn list_push_subscriptions(&self, tn_id: TnId) -> ClResult<Vec<PushSubscription>>;
1807
1808 async fn create_push_subscription(
1814 &self,
1815 tn_id: TnId,
1816 subscription: &PushSubscriptionData,
1817 ) -> ClResult<u64>;
1818
1819 async fn delete_push_subscription(&self, tn_id: TnId, subscription_id: u64) -> ClResult<()>;
1824
1825 async fn create_share_entry(
1830 &self,
1831 tn_id: TnId,
1832 resource_type: char,
1833 resource_id: &str,
1834 created_by: &str,
1835 entry: &CreateShareEntry,
1836 ) -> ClResult<ShareEntry>;
1837
1838 async fn delete_share_entry(&self, tn_id: TnId, id: i64) -> ClResult<()>;
1840
1841 async fn update_share_entry(
1847 &self,
1848 tn_id: TnId,
1849 id: i64,
1850 resource_type: char,
1851 resource_id: &str,
1852 opts: &UpdateShareEntryOptions,
1853 ) -> ClResult<ShareEntry>;
1854
1855 async fn list_share_entries(
1857 &self,
1858 tn_id: TnId,
1859 resource_type: char,
1860 resource_id: &str,
1861 ) -> ClResult<Vec<ShareEntry>>;
1862
1863 async fn list_share_entries_by_subject(
1866 &self,
1867 tn_id: TnId,
1868 subject_type: Option<char>,
1869 subject_id: &str,
1870 ) -> ClResult<Vec<ShareEntry>>;
1871
1872 async fn check_share_access(
1875 &self,
1876 tn_id: TnId,
1877 resource_type: char,
1878 resource_id: &str,
1879 subject_type: char,
1880 subject_id: &str,
1881 ) -> ClResult<Option<char>>;
1882
1883 async fn read_share_entry(&self, tn_id: TnId, id: i64) -> ClResult<Option<ShareEntry>>;
1885
1886 async fn install_app(&self, tn_id: TnId, install: &InstallApp) -> ClResult<()>;
1891
1892 async fn uninstall_app(&self, tn_id: TnId, app_name: &str, publisher_tag: &str)
1894 -> ClResult<()>;
1895
1896 async fn list_installed_apps(
1898 &self,
1899 tn_id: TnId,
1900 search: Option<&str>,
1901 ) -> ClResult<Vec<InstalledApp>>;
1902
1903 async fn get_installed_app(
1905 &self,
1906 tn_id: TnId,
1907 app_name: &str,
1908 publisher_tag: &str,
1909 ) -> ClResult<Option<InstalledApp>>;
1910
1911 async fn create_address_book(
1916 &self,
1917 tn_id: TnId,
1918 name: &str,
1919 description: Option<&str>,
1920 ) -> ClResult<AddressBook>;
1921
1922 async fn list_address_books(&self, tn_id: TnId) -> ClResult<Vec<AddressBook>>;
1924
1925 async fn get_address_book(&self, tn_id: TnId, ab_id: u64) -> ClResult<Option<AddressBook>>;
1927
1928 async fn get_address_book_by_name(
1930 &self,
1931 tn_id: TnId,
1932 name: &str,
1933 ) -> ClResult<Option<AddressBook>>;
1934
1935 async fn update_address_book(
1937 &self,
1938 tn_id: TnId,
1939 ab_id: u64,
1940 patch: &UpdateAddressBookData,
1941 ) -> ClResult<()>;
1942
1943 async fn delete_address_book(&self, tn_id: TnId, ab_id: u64) -> ClResult<()>;
1945
1946 async fn list_contacts(
1949 &self,
1950 tn_id: TnId,
1951 ab_id: Option<u64>,
1952 opts: &ListContactOptions,
1953 ) -> ClResult<Vec<ContactView>>;
1954
1955 async fn get_contact(&self, tn_id: TnId, ab_id: u64, uid: &str) -> ClResult<Option<Contact>>;
1957
1958 async fn upsert_contact(
1961 &self,
1962 tn_id: TnId,
1963 ab_id: u64,
1964 uid: &str,
1965 vcard: &str,
1966 etag: &str,
1967 extracted: &ContactExtracted,
1968 ) -> ClResult<Box<str>>;
1969
1970 async fn delete_contact(&self, tn_id: TnId, ab_id: u64, uid: &str) -> ClResult<()>;
1973
1974 async fn get_contacts_by_uids(
1976 &self,
1977 tn_id: TnId,
1978 ab_id: u64,
1979 uids: &[&str],
1980 ) -> ClResult<Vec<Contact>>;
1981
1982 async fn list_contacts_since(
1988 &self,
1989 tn_id: TnId,
1990 ab_id: u64,
1991 since: Option<Timestamp>,
1992 limit: Option<u32>,
1993 ) -> ClResult<Vec<ContactSyncEntry>>;
1994
1995 async fn list_contacts_by_profile(
1997 &self,
1998 tn_id: TnId,
1999 profile_id_tag: &str,
2000 ) -> ClResult<Vec<Contact>>;
2001
2002 async fn create_calendar(&self, tn_id: TnId, input: &CreateCalendarData) -> ClResult<Calendar>;
2007
2008 async fn list_calendars(&self, tn_id: TnId) -> ClResult<Vec<Calendar>>;
2010
2011 async fn get_calendar(&self, tn_id: TnId, cal_id: u64) -> ClResult<Option<Calendar>>;
2013
2014 async fn get_calendar_by_name(&self, tn_id: TnId, name: &str) -> ClResult<Option<Calendar>>;
2016
2017 async fn update_calendar(
2019 &self,
2020 tn_id: TnId,
2021 cal_id: u64,
2022 patch: &UpdateCalendarData,
2023 ) -> ClResult<()>;
2024
2025 async fn delete_calendar(&self, tn_id: TnId, cal_id: u64) -> ClResult<()>;
2027
2028 async fn list_calendar_objects(
2030 &self,
2031 tn_id: TnId,
2032 cal_id: u64,
2033 opts: &ListCalendarObjectOptions,
2034 ) -> ClResult<Vec<CalendarObjectView>>;
2035
2036 async fn get_calendar_object(
2040 &self,
2041 tn_id: TnId,
2042 cal_id: u64,
2043 uid: &str,
2044 ) -> ClResult<Option<CalendarObject>>;
2045
2046 async fn get_calendar_object_override(
2048 &self,
2049 tn_id: TnId,
2050 cal_id: u64,
2051 uid: &str,
2052 recurrence_id: Timestamp,
2053 ) -> ClResult<Option<CalendarObject>>;
2054
2055 async fn list_calendar_object_overrides(
2057 &self,
2058 tn_id: TnId,
2059 cal_id: u64,
2060 uid: &str,
2061 ) -> ClResult<Vec<CalendarObject>>;
2062
2063 async fn delete_calendar_object_override(
2065 &self,
2066 tn_id: TnId,
2067 cal_id: u64,
2068 uid: &str,
2069 recurrence_id: Timestamp,
2070 ) -> ClResult<()>;
2071
2072 async fn upsert_calendar_object(
2076 &self,
2077 tn_id: TnId,
2078 cal_id: u64,
2079 uid: &str,
2080 ical: &str,
2081 etag: &str,
2082 extracted: &CalendarObjectExtracted,
2083 ) -> ClResult<Box<str>>;
2084
2085 async fn delete_calendar_object(&self, tn_id: TnId, cal_id: u64, uid: &str) -> ClResult<()>;
2088
2089 async fn split_calendar_object_series(
2100 &self,
2101 tn_id: TnId,
2102 cal_id: u64,
2103 master: CalendarObjectWrite<'_>,
2104 tail: CalendarObjectWrite<'_>,
2105 split_at: Timestamp,
2106 ) -> ClResult<(Box<str>, Box<str>)>;
2107
2108 async fn get_calendar_objects_by_uids(
2110 &self,
2111 tn_id: TnId,
2112 cal_id: u64,
2113 uids: &[&str],
2114 ) -> ClResult<Vec<CalendarObject>>;
2115
2116 async fn list_calendar_objects_since(
2119 &self,
2120 tn_id: TnId,
2121 cal_id: u64,
2122 since: Option<Timestamp>,
2123 limit: Option<u32>,
2124 ) -> ClResult<Vec<CalendarObjectSyncEntry>>;
2125
2126 async fn query_calendar_objects_in_range(
2131 &self,
2132 tn_id: TnId,
2133 cal_id: u64,
2134 component: Option<&str>,
2135 start: Option<Timestamp>,
2136 end: Option<Timestamp>,
2137 ) -> ClResult<Vec<CalendarObject>>;
2138}
2139
2140#[cfg(test)]
2141mod tests {
2142 use super::*;
2143 #[test]
2144 fn test_deserialize_list_action_options_with_multiple_statuses() {
2145 let query = "status=C,N&type=POST,REPLY";
2146 let opts: ListActionOptions =
2147 serde_urlencoded::from_str(query).expect("should deserialize");
2148
2149 assert!(opts.status.is_some());
2150 let statuses = opts.status.expect("status should be Some");
2151 assert_eq!(statuses.len(), 2);
2152 assert_eq!(statuses[0].as_str(), "C");
2153 assert_eq!(statuses[1].as_str(), "N");
2154
2155 assert!(opts.typ.is_some());
2156 let types = opts.typ.expect("type should be Some");
2157 assert_eq!(types.len(), 2);
2158 assert_eq!(types[0].as_str(), "POST");
2159 assert_eq!(types[1].as_str(), "REPLY");
2160 }
2161
2162 #[test]
2163 fn test_deserialize_list_action_options_without_status() {
2164 let query = "issuer=alice";
2165 let opts: ListActionOptions =
2166 serde_urlencoded::from_str(query).expect("should deserialize");
2167
2168 assert!(opts.status.is_none());
2169 assert!(opts.typ.is_none());
2170 assert_eq!(opts.issuer.as_deref(), Some("alice"));
2171 }
2172
2173 #[test]
2174 fn test_deserialize_list_action_options_single_status() {
2175 let query = "status=C";
2176 let opts: ListActionOptions =
2177 serde_urlencoded::from_str(query).expect("should deserialize");
2178
2179 assert!(opts.status.is_some());
2180 let statuses = opts.status.expect("status should be Some");
2181 assert_eq!(statuses.len(), 1);
2182 assert_eq!(statuses[0].as_str(), "C");
2183 }
2184
2185 #[test]
2186 fn test_deserialize_list_action_options_audience_type() {
2187 let opts: ListActionOptions = serde_urlencoded::from_str("audienceType=personal")
2188 .expect("should deserialize personal");
2189 assert!(matches!(opts.audience_type, Some(AudienceType::Personal)));
2190
2191 let opts: ListActionOptions = serde_urlencoded::from_str("audienceType=community")
2192 .expect("should deserialize community");
2193 assert!(matches!(opts.audience_type, Some(AudienceType::Community)));
2194
2195 let opts: ListActionOptions =
2196 serde_urlencoded::from_str("issuer=alice").expect("should deserialize");
2197 assert!(opts.audience_type.is_none());
2198
2199 let res: Result<ListActionOptions, _> = serde_urlencoded::from_str("audienceType=garbage");
2200 assert!(res.is_err(), "garbage audienceType should error");
2201 }
2202
2203 #[test]
2204 fn test_deserialize_list_action_options_multi_visibility() {
2205 let opts: ListActionOptions =
2206 serde_urlencoded::from_str("visibility=F,C").expect("should deserialize");
2207 let v = opts.visibility.expect("visibility should be Some");
2208 assert_eq!(v.len(), 2);
2209 assert_eq!(v[0].as_str(), "F");
2210 assert_eq!(v[1].as_str(), "C");
2211
2212 let opts: ListActionOptions =
2213 serde_urlencoded::from_str("visibility=P").expect("should deserialize");
2214 let v = opts.visibility.expect("visibility should be Some");
2215 assert_eq!(v.len(), 1);
2216 assert_eq!(v[0].as_str(), "P");
2217
2218 let opts: ListActionOptions =
2219 serde_urlencoded::from_str("issuer=alice").expect("should deserialize");
2220 assert!(opts.visibility.is_none());
2221 }
2222
2223 #[test]
2224 fn test_deserialize_list_action_options_visibility_with_direct() {
2225 let opts: ListActionOptions =
2226 serde_urlencoded::from_str("visibility=D,F").expect("should deserialize");
2227 let v = opts.visibility.expect("visibility should be Some");
2228 assert_eq!(v.len(), 2);
2229 assert_eq!(v[0].as_str(), "D");
2230 assert_eq!(v[1].as_str(), "F");
2231 }
2232
2233 #[test]
2234 fn test_broken_reason_as_str_matches_serde() {
2235 for reason in [BrokenReason::Deleted, BrokenReason::Revoked] {
2236 let via_serde = serde_json::to_value(reason)
2237 .expect("serialize")
2238 .as_str()
2239 .expect("string variant")
2240 .to_string();
2241 assert_eq!(reason.as_str(), via_serde, "as_str diverged from serde for {:?}", reason);
2242 }
2243 }
2244}
2245
2246