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 #[serde(skip_serializing_if = "Option::is_none")]
184 pub last_seen_at: Option<Timestamp>,
185 #[serde(skip_serializing_if = "Option::is_none")]
187 pub notify_email_direct_at: Option<Timestamp>,
188 #[serde(skip_serializing_if = "Option::is_none")]
190 pub notify_email_engagement_at: Option<Timestamp>,
191 #[serde(skip_serializing_if = "Option::is_none")]
193 pub notify_email_social_at: Option<Timestamp>,
194 pub x: HashMap<S, S>,
195}
196
197#[derive(Debug, Default)]
199pub struct ListTenantsMetaOptions {
200 pub limit: Option<u32>,
201 pub offset: Option<u32>,
202}
203
204#[skip_serializing_none]
206#[derive(Debug, Clone, Serialize)]
207#[serde(rename_all = "camelCase")]
208pub struct TenantListMeta {
209 pub tn_id: TnId,
210 pub id_tag: Box<str>,
211 pub name: Box<str>,
212 #[serde(rename = "type")]
213 pub typ: ProfileType,
214 pub profile_pic: Option<Box<str>>,
215 #[serde(serialize_with = "serialize_timestamp_iso")]
216 pub created_at: Timestamp,
217}
218
219#[derive(Debug, Default, Deserialize)]
220pub struct UpdateTenantData {
221 #[serde(rename = "idTag", default)]
222 pub id_tag: Patch<String>,
223 #[serde(default)]
224 pub name: Patch<String>,
225 #[serde(rename = "type", default)]
226 pub typ: Patch<ProfileType>,
227 #[serde(rename = "profilePic", default)]
228 pub profile_pic: Patch<String>,
229 #[serde(rename = "coverPic", default)]
230 pub cover_pic: Patch<String>,
231 #[serde(default)]
233 pub x: Option<std::collections::HashMap<String, Option<String>>>,
234 #[serde(skip)]
237 pub last_seen_at: Patch<Timestamp>,
238 #[serde(skip)]
241 pub notify_email_direct_at: Patch<Timestamp>,
242 #[serde(skip)]
243 pub notify_email_engagement_at: Patch<Timestamp>,
244 #[serde(skip)]
245 pub notify_email_social_at: Patch<Timestamp>,
246}
247
248#[derive(Debug)]
249pub struct Profile<S: AsRef<str>> {
250 pub id_tag: S,
251 pub name: S,
252 pub typ: ProfileType,
253 pub profile_pic: Option<S>,
254 pub status: Option<ProfileStatus>,
255 pub synced_at: Option<Timestamp>,
256 pub following: bool,
257 pub follower: bool,
258 pub connected: ProfileConnectionStatus,
259 pub roles: Option<Box<[Box<str>]>>,
260 pub trust: Option<ProfileTrust>,
261 pub feed_read_at: Option<Timestamp>,
263 pub msg_read_at: Option<Timestamp>,
265 pub hidden_in_home: Option<bool>,
269}
270
271#[derive(Debug, Default, Deserialize)]
272pub struct ListProfileOptions {
273 #[serde(rename = "type")]
274 pub typ: Option<ProfileType>,
275 pub status: Option<Box<[ProfileStatus]>>,
276 pub connected: Option<ProfileConnectionStatus>,
277 pub following: Option<bool>,
278 pub follower: Option<bool>,
279 pub q: Option<String>,
280 pub id_tag: Option<String>,
281 pub trust_set: Option<bool>,
285 pub hidden_in_home: Option<bool>,
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize)]
292#[serde(rename_all = "camelCase")]
293pub struct ProfileData {
294 pub id_tag: Box<str>,
295 pub name: Box<str>,
296 #[serde(rename = "type")]
297 pub r#type: Box<str>, pub profile_pic: Option<Box<str>>,
299 #[serde(default, skip_serializing_if = "Option::is_none")]
301 pub status: Option<Box<str>>,
302 #[serde(serialize_with = "serialize_timestamp_iso")]
303 pub created_at: Timestamp,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct ProfileList {
309 pub profiles: Vec<ProfileData>,
310 pub total: usize,
311 pub limit: usize,
312 pub offset: usize,
313}
314
315#[derive(Debug, Default, Deserialize)]
316pub struct UpdateProfileData {
317 #[serde(default)]
319 pub name: Patch<Box<str>>,
320 #[serde(default, rename = "profilePic")]
321 pub profile_pic: Patch<Option<Box<str>>>,
322 #[serde(default)]
323 pub roles: Patch<Option<Vec<Box<str>>>>,
324
325 #[serde(default)]
327 pub status: Patch<ProfileStatus>,
328
329 #[serde(default)]
331 pub synced: Patch<bool>,
332 #[serde(default)]
333 pub trust: Patch<ProfileTrust>,
334 #[serde(default)]
337 pub hidden_in_home: Patch<bool>,
338
339 #[serde(default)]
341 pub etag: Patch<Box<str>>,
342}
343
344#[derive(Debug, Clone, Copy, PartialEq, Eq)]
346pub enum UpsertResult {
347 Created,
349 Updated,
351}
352
353#[derive(Default)]
374pub struct UpsertProfileFields {
375 pub name: Patch<Box<str>>,
376 pub typ: Patch<ProfileType>,
377 pub profile_pic: Patch<Option<Box<str>>>,
378 pub roles: Patch<Option<Vec<Box<str>>>>,
379 pub status: Patch<ProfileStatus>,
380 pub synced: Patch<bool>,
381 pub following: Patch<bool>,
382 pub follower: Patch<bool>,
383 pub connected: Patch<ProfileConnectionStatus>,
384 pub trust: Patch<ProfileTrust>,
385 pub hidden_in_home: Patch<bool>,
389 pub etag: Patch<Box<str>>,
390}
391
392impl UpsertProfileFields {
393 pub fn from_update(update: UpdateProfileData) -> Self {
398 Self {
399 name: update.name,
400 typ: Patch::Undefined,
401 profile_pic: update.profile_pic,
402 roles: update.roles,
403 status: update.status,
404 synced: update.synced,
405 following: Patch::Undefined,
409 follower: Patch::Undefined,
410 connected: Patch::Undefined,
411 trust: update.trust,
412 hidden_in_home: update.hidden_in_home,
413 etag: update.etag,
414 }
415 }
416}
417
418#[derive(Debug, Clone)]
423pub struct ActionData {
424 pub subject: Option<Box<str>>,
425 pub reactions: Option<Box<str>>,
426 pub comments: Option<i64>,
428 pub comments_ts: Option<Timestamp>,
431 pub stat_at: Option<Timestamp>,
438}
439
440#[derive(Debug, Clone, Default)]
442pub struct UpdateActionDataOptions {
443 pub subject: Patch<String>,
444 pub reactions: Patch<String>,
445 pub comments: Patch<u32>,
447 pub comments_ts: Patch<Timestamp>,
449 pub reposts: Patch<u32>,
450 pub stat_at: Patch<Timestamp>,
452 pub status: Patch<char>,
453 pub visibility: Patch<char>,
454 pub x: Patch<serde_json::Value>, pub content: Patch<String>,
456 pub attachments: Patch<String>, pub flags: Patch<String>,
458 pub sub_level: Patch<char>,
460 pub sub_typ: Patch<String>,
461 pub created_at: Patch<Timestamp>,
468}
469
470#[derive(Debug, Clone, Default)]
472pub struct FinalizeActionOptions<'a> {
473 pub attachments: Option<&'a [&'a str]>,
474 pub subject: Option<&'a str>,
475 pub audience_tag: Option<&'a str>,
476 pub key: Option<&'a str>,
477}
478
479fn deserialize_split<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
480where
481 D: serde::Deserializer<'de>,
482{
483 let s = String::deserialize(deserializer)?;
484 let values: Vec<String> =
485 s.split(',').map(|v| v.trim().to_string()).filter(|v| !v.is_empty()).collect();
486 if values.is_empty() { Ok(None) } else { Ok(Some(values)) }
487}
488
489#[derive(Debug, Clone, Copy, Deserialize)]
495#[serde(rename_all = "lowercase")]
496pub enum AudienceType {
497 Personal,
498 Community,
499}
500
501#[derive(Debug, Clone, Copy)]
504pub enum ActionCountGroupBy {
505 SubType,
506}
507
508#[derive(Debug, Default, Deserialize)]
510#[serde(deny_unknown_fields)]
511pub struct ListActionOptions {
512 pub limit: Option<u32>,
514 pub cursor: Option<String>,
516 pub sort: Option<String>,
520 #[serde(rename = "sortDir")]
522 pub sort_dir: Option<String>,
523 #[serde(default, rename = "type", deserialize_with = "deserialize_split")]
524 pub typ: Option<Vec<String>>,
525 #[serde(default, deserialize_with = "deserialize_split")]
526 pub status: Option<Vec<String>>,
527 pub tag: Option<String>,
528 pub search: Option<String>,
529 #[serde(default, deserialize_with = "deserialize_split")]
530 pub visibility: Option<Vec<String>>,
531 pub issuer: Option<String>,
532 pub audience: Option<String>,
533 #[serde(rename = "audienceType")]
534 pub audience_type: Option<AudienceType>,
535 pub involved: Option<String>,
536 #[serde(skip)]
538 pub viewer_id_tag: Option<String>,
539 #[serde(rename = "actionId")]
540 pub action_id: Option<String>,
541 #[serde(rename = "parentId")]
542 pub parent_id: Option<String>,
543 #[serde(rename = "rootId")]
544 pub root_id: Option<String>,
545 #[serde(default, deserialize_with = "deserialize_split")]
546 pub subject: Option<Vec<String>>,
547 #[serde(rename = "createdAfter")]
548 pub created_after: Option<Timestamp>,
549 #[serde(rename = "createdBefore")]
550 pub created_before: Option<Timestamp>,
551 pub subscribed: Option<bool>,
554 #[serde(rename = "includeTokens")]
557 pub include_tokens: Option<bool>,
558 #[serde(rename = "includeSubject")]
564 pub include_subject: Option<bool>,
565 #[serde(skip)]
569 pub exclude_issuer_profile_status: Option<Box<[ProfileStatus]>>,
570 #[serde(skip)]
575 pub exclude_sub_typ: Option<Box<[Box<str>]>>,
576 #[serde(skip)]
581 pub exclude_audiences: Option<Box<[String]>>,
582 #[serde(rename = "excludeOwnIssuer")]
585 pub exclude_own_issuer: Option<bool>,
586 pub count: Option<bool>,
590 #[serde(skip)]
601 pub visibility_guard: Patch<String>,
602}
603
604#[skip_serializing_none]
605#[derive(Debug, Clone, Serialize, serde::Deserialize)]
606pub struct ProfileInfo {
607 #[serde(rename = "idTag")]
608 pub id_tag: Box<str>,
609 pub name: Box<str>,
610 #[serde(rename = "type")]
611 pub typ: ProfileType,
612 #[serde(rename = "profilePic")]
613 pub profile_pic: Option<Box<str>>,
614}
615
616#[derive(Default)]
617pub struct Action<S: AsRef<str>> {
618 pub action_id: S,
619 pub typ: S,
620 pub sub_typ: Option<S>,
621 pub issuer_tag: S,
622 pub parent_id: Option<S>,
623 pub root_id: Option<S>,
624 pub audience_tag: Option<S>,
625 pub content: Option<S>,
626 pub attachments: Option<Vec<S>>,
627 pub subject: Option<S>,
628 pub created_at: Timestamp,
629 pub expires_at: Option<Timestamp>,
630 pub visibility: Option<char>, pub flags: Option<S>, pub x: Option<serde_json::Value>, }
634
635#[skip_serializing_none]
636#[derive(Debug, Clone, Serialize)]
637pub struct AttachmentView {
638 #[serde(rename = "fileId")]
639 pub file_id: Box<str>,
640 pub dim: Option<(u32, u32)>,
641 #[serde(rename = "localVariants")]
642 pub local_variants: Option<Vec<Box<str>>>,
643}
644
645#[skip_serializing_none]
646#[derive(Debug, Clone, Serialize)]
647#[serde(rename_all = "camelCase")]
648pub struct ActionView {
649 pub action_id: Box<str>,
650 #[serde(rename = "type")]
651 pub typ: Box<str>,
652 #[serde(rename = "subType")]
653 pub sub_typ: Option<Box<str>>,
654 pub parent_id: Option<Box<str>>,
655 pub root_id: Option<Box<str>>,
656 pub issuer: ProfileInfo,
657 pub audience: Option<ProfileInfo>,
658 pub content: Option<serde_json::Value>,
659 pub attachments: Option<Vec<AttachmentView>>,
660 pub subject: Option<Box<str>>,
661 pub subject_profile: Option<ProfileInfo>,
662 #[serde(default, skip_serializing_if = "Option::is_none")]
667 pub subject_action: Option<Box<ActionView>>,
668 #[serde(serialize_with = "serialize_timestamp_iso")]
669 pub created_at: Timestamp,
670 #[serde(
676 serialize_with = "serialize_timestamp_iso_opt",
677 skip_serializing_if = "Option::is_none"
678 )]
679 pub received_at: Option<Timestamp>,
680 #[serde(serialize_with = "serialize_timestamp_iso_opt")]
681 pub expires_at: Option<Timestamp>,
682 pub status: Option<Box<str>>,
683 pub stat: Option<serde_json::Value>,
684 pub visibility: Option<char>,
685 pub flags: Option<Box<str>>, #[serde(rename = "subLevel", skip_serializing_if = "Option::is_none")]
688 pub sub_level: Option<Box<str>>,
689 pub x: Option<serde_json::Value>, #[serde(default, skip_serializing_if = "Option::is_none")]
693 pub token: Option<Box<str>>,
694}
695
696#[derive(Debug)]
699pub enum FileId<S: AsRef<str>> {
700 FileId(S),
701 FId(u64),
702}
703
704pub enum ActionId<S: AsRef<str>> {
705 ActionId(S),
706 AId(u64),
707}
708
709#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
712pub enum FileStatus {
713 #[serde(rename = "A")]
714 Active,
715 #[serde(rename = "P")]
716 Pending,
717 #[serde(rename = "D")]
718 Deleted,
719}
720
721#[skip_serializing_none]
723#[derive(Debug, Clone, Default, Serialize, serde::Deserialize)]
724#[serde(rename_all = "camelCase")]
725pub struct FileUserData {
726 #[serde(default, serialize_with = "serialize_timestamp_iso_opt")]
727 pub accessed_at: Option<Timestamp>,
728 #[serde(default, serialize_with = "serialize_timestamp_iso_opt")]
729 pub modified_at: Option<Timestamp>,
730 #[serde(default)]
731 pub pinned: bool,
732 #[serde(default)]
733 pub starred: bool,
734 #[serde(default)]
740 pub access_level: Option<crate::types::AccessLevel>,
741}
742
743#[skip_serializing_none]
744#[derive(Debug, Clone, Serialize, serde::Deserialize)]
745#[serde(rename_all = "camelCase")]
746pub struct FileView {
747 pub file_id: Box<str>,
748 #[serde(default)]
749 pub parent_id: Option<Box<str>>, #[serde(default)]
751 pub root_id: Option<Box<str>>, #[serde(default)]
753 pub owner: Option<ProfileInfo>,
754 #[serde(default)]
755 pub creator: Option<ProfileInfo>,
756 #[serde(default)]
757 pub preset: Option<Box<str>>,
758 #[serde(default)]
759 pub content_type: Option<Box<str>>,
760 pub file_name: Box<str>,
761 #[serde(default)]
762 pub file_tp: Option<Box<str>>, #[serde(serialize_with = "serialize_timestamp_iso")]
764 pub created_at: Timestamp,
765 #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
766 pub accessed_at: Option<Timestamp>, #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
768 pub modified_at: Option<Timestamp>, pub status: FileStatus,
770 #[serde(default)]
771 pub tags: Option<Vec<Box<str>>>,
772 #[serde(default)]
773 pub visibility: Option<char>, #[serde(default)]
779 pub hidden: bool,
780 #[serde(default)]
781 pub access_level: Option<crate::types::AccessLevel>, #[serde(default)]
783 pub user_data: Option<FileUserData>, #[serde(default)]
785 pub x: Option<serde_json::Value>, #[serde(default)]
790 pub parent_name: Option<Box<str>>,
791 #[serde(default)]
795 pub path: Option<Vec<PathSegment>>,
796 #[serde(default, serialize_with = "crate::types::serialize_timestamp_iso_opt")]
803 pub broken_at: Option<Timestamp>,
804 #[serde(default)]
807 pub broken_reason: Option<BrokenReason>,
808}
809
810#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
816#[serde(rename_all = "lowercase")]
817pub enum BrokenReason {
818 Deleted,
820 Revoked,
822}
823
824impl BrokenReason {
825 pub fn as_str(&self) -> &'static str {
826 match self {
827 Self::Deleted => "deleted",
828 Self::Revoked => "revoked",
829 }
830 }
831}
832
833#[derive(Debug, Clone, Serialize, serde::Deserialize)]
835#[serde(rename_all = "camelCase")]
836pub struct PathSegment {
837 pub id: Box<str>,
838 pub name: Box<str>,
839}
840
841#[skip_serializing_none]
842#[derive(Debug, Clone, Serialize)]
843pub struct FileVariant<S: AsRef<str> + Debug> {
844 #[serde(rename = "variantId")]
845 pub variant_id: S,
846 pub variant: S,
847 pub format: S,
848 pub size: u64,
849 pub resolution: (u32, u32),
850 pub available: bool,
851 #[serde(skip_serializing_if = "std::ops::Not::not")]
853 pub global: bool,
854 pub duration: Option<f64>,
856 pub bitrate: Option<u32>,
858 #[serde(rename = "pageCount")]
860 pub page_count: Option<u32>,
861}
862
863impl<S: AsRef<str> + Debug> PartialEq for FileVariant<S> {
866 fn eq(&self, other: &Self) -> bool {
867 self.variant_id.as_ref() == other.variant_id.as_ref()
868 && self.variant.as_ref() == other.variant.as_ref()
869 && self.format.as_ref() == other.format.as_ref()
870 && self.size == other.size
871 && self.resolution == other.resolution
872 && self.available == other.available
873 && self.duration == other.duration
874 && self.bitrate == other.bitrate
875 && self.page_count == other.page_count
876 }
877}
878
879impl<S: AsRef<str> + Debug> Eq for FileVariant<S> {}
880
881impl<S: AsRef<str> + Debug + Ord> PartialOrd for FileVariant<S> {
882 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
883 Some(self.cmp(other))
884 }
885}
886
887impl<S: AsRef<str> + Debug + Ord> Ord for FileVariant<S> {
888 fn cmp(&self, other: &Self) -> Ordering {
889 self.size
890 .cmp(&other.size)
891 .then_with(|| self.resolution.0.cmp(&other.resolution.0))
892 .then_with(|| self.resolution.1.cmp(&other.resolution.1))
893 .then_with(|| self.variant.as_ref().cmp(other.variant.as_ref()))
894 }
895}
896
897#[derive(Debug, Default, Deserialize)]
902#[serde(deny_unknown_fields)]
903#[allow(clippy::struct_excessive_bools)]
904pub struct ListFileOptions {
905 pub limit: Option<u32>,
907 pub cursor: Option<String>,
909 #[serde(default, rename = "fileId", deserialize_with = "deserialize_split")]
910 pub file_id: Option<Vec<String>>,
911 #[serde(rename = "parentId")]
912 pub parent_id: Option<String>, #[serde(rename = "notParentId")]
917 pub not_parent_id: Option<String>,
918 #[serde(rename = "rootId")]
919 pub root_id: Option<String>, pub tag: Option<String>,
921 pub preset: Option<String>,
922 pub variant: Option<String>,
923 pub status: Option<FileStatus>,
925 #[serde(default, rename = "fileTp", deserialize_with = "deserialize_split")]
926 pub file_type: Option<Vec<String>>,
927 #[serde(default, rename = "contentType", deserialize_with = "deserialize_split")]
929 pub content_type: Option<Vec<String>>,
930 #[serde(default, rename = "includeFolders")]
933 pub include_folders: bool,
934 #[serde(rename = "fileName")]
936 pub file_name: Option<String>,
937 #[serde(rename = "ownerIdTag")]
939 pub owner_id_tag: Option<String>,
940 #[serde(rename = "notOwnerIdTag")]
942 pub not_owner_id_tag: Option<String>,
943 #[serde(default, rename = "localOnly")]
948 pub local_only: bool,
949 pub pinned: Option<bool>,
951 pub starred: Option<bool>,
953 pub hidden: Option<bool>,
958 pub sort: Option<String>,
960 #[serde(rename = "sortDir")]
962 pub sort_dir: Option<String>,
963 #[serde(skip)]
965 pub user_id_tag: Option<String>,
966 #[serde(skip)]
969 pub scope_file_id: Option<String>,
970 #[serde(skip)]
974 pub visible_levels: Option<Vec<char>>,
975 #[serde(default, rename = "withParent")]
979 pub with_parent: bool,
980 #[serde(default, rename = "withPath")]
983 pub with_path: bool,
984}
985
986#[derive(Debug, Clone, Default)]
987pub struct CreateFile {
988 pub orig_variant_id: Option<Box<str>>,
989 pub file_id: Option<Box<str>>,
990 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>>,
995 pub content_type: Box<str>,
996 pub file_name: Box<str>,
997 pub file_tp: Option<Box<str>>, pub created_at: Option<Timestamp>,
999 pub tags: Option<Vec<Box<str>>>,
1000 pub x: Option<serde_json::Value>,
1001 pub visibility: Option<char>, pub hidden: bool,
1005 pub status: Option<FileStatus>, }
1007
1008#[derive(Debug, Clone, Deserialize)]
1009pub struct CreateFileVariant {
1010 pub variant: Box<str>,
1011 pub format: Box<str>,
1012 pub resolution: (u32, u32),
1013 pub size: u64,
1014 pub available: bool,
1015}
1016
1017#[derive(Debug, Clone, Default, Deserialize)]
1019pub struct UpdateFileOptions {
1020 #[serde(default, rename = "fileName")]
1021 pub file_name: Patch<String>,
1022 #[serde(default, rename = "parentId")]
1023 pub parent_id: Patch<String>, #[serde(default)]
1025 pub visibility: Patch<char>,
1026 #[serde(default)]
1027 pub status: Patch<char>,
1028 #[serde(default)]
1031 pub hidden: Patch<bool>,
1032 #[serde(default, rename = "contentType", skip_deserializing)]
1035 pub content_type: Patch<String>,
1036 #[serde(default, rename = "fileTp", skip_deserializing)]
1037 pub file_tp: Patch<String>,
1038 #[serde(default, skip_deserializing)]
1039 pub tags: Patch<Vec<String>>,
1040 #[serde(default, skip_deserializing)]
1041 pub preset: Patch<String>,
1042 #[serde(default, skip_deserializing)]
1043 pub x: Patch<serde_json::Value>,
1044 #[serde(default, skip_deserializing)]
1048 pub broken: Patch<BrokenReason>,
1049}
1050
1051#[skip_serializing_none]
1055#[derive(Debug, Clone, Serialize)]
1056#[serde(rename_all = "camelCase")]
1057pub struct ShareEntry {
1058 pub id: i64,
1059 pub resource_type: char,
1060 pub resource_id: Box<str>,
1061 pub subject_type: char,
1062 pub subject_id: Box<str>,
1063 pub permission: char,
1064 #[serde(serialize_with = "serialize_timestamp_iso_opt")]
1065 pub expires_at: Option<Timestamp>,
1066 pub created_by: Box<str>,
1067 #[serde(serialize_with = "serialize_timestamp_iso")]
1068 pub created_at: Timestamp,
1069 pub subject_file_name: Option<Box<str>>,
1071 pub subject_content_type: Option<Box<str>>,
1072 pub subject_file_tp: Option<Box<str>>,
1073}
1074
1075#[derive(Debug, Deserialize)]
1076#[serde(rename_all = "camelCase")]
1077pub struct CreateShareEntry {
1078 pub subject_type: char,
1079 pub subject_id: String,
1080 pub permission: char,
1081 pub expires_at: Option<Timestamp>,
1082}
1083
1084#[derive(Debug, Default)]
1091pub struct UpdateShareEntryOptions {
1092 pub permission: Patch<char>,
1095 pub expires_at: Patch<Timestamp>,
1097}
1098
1099#[skip_serializing_none]
1104#[derive(Debug, Clone, Serialize, Deserialize)]
1105pub struct PushSubscriptionData {
1106 pub endpoint: String,
1108 #[serde(rename = "expirationTime")]
1110 pub expiration_time: Option<i64>,
1111 pub keys: PushSubscriptionKeys,
1113}
1114
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1117pub struct PushSubscriptionKeys {
1118 pub p256dh: String,
1120 pub auth: String,
1122}
1123
1124#[derive(Debug, Clone, Serialize)]
1126#[serde(rename_all = "camelCase")]
1127pub struct PushSubscription {
1128 pub id: u64,
1130 pub subscription: PushSubscriptionData,
1132 #[serde(serialize_with = "serialize_timestamp_iso")]
1134 pub created_at: Timestamp,
1135}
1136
1137pub struct Task {
1140 pub task_id: u64,
1141 pub tn_id: TnId,
1142 pub kind: Box<str>,
1143 pub status: char,
1144 pub created_at: Timestamp,
1145 pub next_at: Option<Timestamp>,
1146 pub input: Box<str>,
1147 pub output: Box<str>,
1148 pub deps: Box<[u64]>,
1149 pub retry: Option<Box<str>>,
1150 pub cron: Option<Box<str>>,
1151}
1152
1153#[derive(Debug, Default)]
1154pub struct TaskPatch {
1155 pub input: Patch<String>,
1156 pub next_at: Patch<Timestamp>,
1157 pub deps: Patch<Vec<u64>>,
1158 pub retry: Patch<String>,
1159 pub cron: Patch<String>,
1160}
1161
1162#[derive(Debug, Default)]
1163pub struct ListTaskOptions {}
1164
1165#[derive(Debug)]
1170pub struct InstallApp {
1171 pub app_name: Box<str>,
1172 pub publisher_tag: Box<str>,
1173 pub version: Box<str>,
1174 pub action_id: Box<str>,
1175 pub file_id: Box<str>,
1176 pub blob_id: Box<str>,
1177 pub capabilities: Option<Vec<Box<str>>>,
1178}
1179
1180#[derive(Debug, Serialize)]
1182#[serde(rename_all = "camelCase")]
1183pub struct InstalledApp {
1184 pub app_name: Box<str>,
1185 pub publisher_tag: Box<str>,
1186 pub version: Box<str>,
1187 pub action_id: Box<str>,
1188 pub file_id: Box<str>,
1189 pub blob_id: Box<str>,
1190 pub status: Box<str>,
1191 pub capabilities: Option<Vec<Box<str>>>,
1192 pub auto_update: bool,
1193 #[serde(serialize_with = "serialize_timestamp_iso")]
1194 pub installed_at: Timestamp,
1195}
1196
1197#[derive(Debug, Clone, Serialize)]
1202#[serde(rename_all = "camelCase")]
1203pub struct AddressBook {
1204 pub ab_id: u64,
1205 pub name: Box<str>,
1206 pub description: Option<Box<str>>,
1207 pub ctag: Box<str>,
1209 #[serde(serialize_with = "serialize_timestamp_iso")]
1210 pub created_at: Timestamp,
1211 #[serde(serialize_with = "serialize_timestamp_iso")]
1212 pub updated_at: Timestamp,
1213}
1214
1215#[derive(Debug, Default)]
1216pub struct UpdateAddressBookData {
1217 pub name: Patch<String>,
1218 pub description: Patch<String>,
1219}
1220
1221#[derive(Debug, Clone, Default)]
1225pub struct ContactExtracted {
1226 pub fn_name: Option<Box<str>>,
1227 pub given_name: Option<Box<str>>,
1228 pub family_name: Option<Box<str>>,
1229 pub email: Option<Box<str>>,
1230 pub emails: Option<Box<str>>,
1231 pub tel: Option<Box<str>>,
1232 pub tels: Option<Box<str>>,
1233 pub org: Option<Box<str>>,
1234 pub title: Option<Box<str>>,
1235 pub note: Option<Box<str>>,
1236 pub photo_uri: Option<Box<str>>,
1237 pub profile_id_tag: Option<Box<str>>,
1238}
1239
1240#[derive(Debug, Clone)]
1242pub struct Contact {
1243 pub c_id: u64,
1244 pub ab_id: u64,
1245 pub uid: Box<str>,
1246 pub etag: Box<str>,
1247 pub vcard: Box<str>,
1248 pub extracted: ContactExtracted,
1249 pub created_at: Timestamp,
1250 pub updated_at: Timestamp,
1251}
1252
1253#[derive(Debug, Clone)]
1256pub struct ContactView {
1257 pub c_id: u64,
1258 pub ab_id: u64,
1259 pub uid: Box<str>,
1260 pub etag: Box<str>,
1261 pub extracted: ContactExtracted,
1262 pub created_at: Timestamp,
1263 pub updated_at: Timestamp,
1264}
1265
1266#[derive(Debug, Clone)]
1269pub struct ContactSyncEntry {
1270 pub uid: Box<str>,
1271 pub etag: Box<str>,
1272 pub deleted: bool,
1273 pub updated_at: Timestamp,
1274}
1275
1276#[derive(Debug, Default)]
1277pub struct ListContactOptions {
1278 pub q: Option<String>,
1280 pub cursor: Option<String>,
1282 pub limit: Option<u32>,
1284}
1285
1286#[derive(Debug, Clone, Serialize)]
1291#[serde(rename_all = "camelCase")]
1292pub struct Calendar {
1293 pub cal_id: u64,
1294 pub name: Box<str>,
1295 pub description: Option<Box<str>>,
1296 pub color: Option<Box<str>>,
1298 pub timezone: Option<Box<str>>,
1300 pub components: Box<str>,
1302 pub ctag: Box<str>,
1304 #[serde(serialize_with = "serialize_timestamp_iso")]
1305 pub created_at: Timestamp,
1306 #[serde(serialize_with = "serialize_timestamp_iso")]
1307 pub updated_at: Timestamp,
1308}
1309
1310#[derive(Debug, Default)]
1311pub struct CreateCalendarData {
1312 pub name: String,
1313 pub description: Option<String>,
1314 pub color: Option<String>,
1315 pub timezone: Option<String>,
1316 pub components: Option<String>,
1318}
1319
1320#[derive(Debug, Default)]
1321pub struct UpdateCalendarData {
1322 pub name: Patch<String>,
1323 pub description: Patch<String>,
1324 pub color: Patch<String>,
1325 pub timezone: Patch<String>,
1326 pub components: Patch<String>,
1327}
1328
1329#[derive(Debug, Clone, Default)]
1332pub struct CalendarObjectExtracted {
1333 pub component: Box<str>,
1335 pub summary: Option<Box<str>>,
1336 pub location: Option<Box<str>>,
1337 pub description: Option<Box<str>>,
1338 pub dtstart: Option<Timestamp>,
1340 pub dtend: Option<Timestamp>,
1342 pub all_day: bool,
1344 pub status: Option<Box<str>>,
1346 pub priority: Option<u8>,
1348 pub organizer: Option<Box<str>>,
1349 pub rrule: Option<Box<str>>,
1351 pub exdate: Vec<Timestamp>,
1353 pub recurrence_id: Option<Timestamp>,
1355 pub sequence: i64,
1356}
1357
1358#[derive(Debug, Clone, Copy)]
1363pub struct CalendarObjectWrite<'a> {
1364 pub uid: &'a str,
1365 pub ical: &'a str,
1366 pub etag: &'a str,
1367 pub extracted: &'a CalendarObjectExtracted,
1368}
1369
1370#[derive(Debug, Clone)]
1372pub struct CalendarObject {
1373 pub co_id: u64,
1374 pub cal_id: u64,
1375 pub uid: Box<str>,
1376 pub etag: Box<str>,
1377 pub ical: Box<str>,
1378 pub extracted: CalendarObjectExtracted,
1379 pub created_at: Timestamp,
1380 pub updated_at: Timestamp,
1381}
1382
1383#[derive(Debug, Clone)]
1385pub struct CalendarObjectView {
1386 pub co_id: u64,
1387 pub cal_id: u64,
1388 pub uid: Box<str>,
1389 pub etag: Box<str>,
1390 pub extracted: CalendarObjectExtracted,
1391 pub created_at: Timestamp,
1392 pub updated_at: Timestamp,
1393}
1394
1395#[derive(Debug, Clone)]
1398pub struct CalendarObjectSyncEntry {
1399 pub uid: Box<str>,
1400 pub etag: Box<str>,
1401 pub deleted: bool,
1402 pub updated_at: Timestamp,
1403}
1404
1405#[derive(Debug, Default)]
1406pub struct ListCalendarObjectOptions {
1407 pub component: Option<String>,
1409 pub q: Option<String>,
1411 pub start: Option<Timestamp>,
1413 pub end: Option<Timestamp>,
1415 pub cursor: Option<String>,
1416 pub limit: Option<u32>,
1417 pub include_exceptions: bool,
1420}
1421
1422#[async_trait]
1423pub trait MetaAdapter: Debug + Send + Sync {
1424 async fn read_tenant(&self, tn_id: TnId) -> ClResult<Tenant<Box<str>>>;
1429
1430 async fn create_tenant(&self, tn_id: TnId, id_tag: &str) -> ClResult<TnId>;
1432
1433 async fn update_tenant(&self, tn_id: TnId, tenant: &UpdateTenantData) -> ClResult<()>;
1435
1436 async fn delete_tenant(&self, tn_id: TnId) -> ClResult<()>;
1438
1439 async fn list_tenants(&self, opts: &ListTenantsMetaOptions) -> ClResult<Vec<TenantListMeta>>;
1441
1442 async fn list_profiles(
1444 &self,
1445 tn_id: TnId,
1446 opts: &ListProfileOptions,
1447 ) -> ClResult<Vec<Profile<Box<str>>>>;
1448
1449 async fn list_follower_tags(&self, tn_id: TnId) -> ClResult<Vec<Box<str>>>;
1454
1455 async fn get_relationships(
1462 &self,
1463 tn_id: TnId,
1464 target_id_tags: &[&str],
1465 ) -> ClResult<HashMap<String, (bool, bool)>>;
1466
1467 async fn read_profile(
1471 &self,
1472 tn_id: TnId,
1473 id_tag: &str,
1474 ) -> ClResult<(Box<str>, Profile<Box<str>>)>;
1475
1476 async fn read_profile_roles(
1478 &self,
1479 tn_id: TnId,
1480 id_tag: &str,
1481 ) -> ClResult<Option<Box<[Box<str>]>>>;
1482
1483 async fn upsert_profile(
1490 &self,
1491 tn_id: TnId,
1492 id_tag: &str,
1493 fields: &UpsertProfileFields,
1494 ) -> ClResult<UpsertResult>;
1495
1496 async fn read_profile_public_key(
1500 &self,
1501 id_tag: &str,
1502 key_id: &str,
1503 ) -> ClResult<(Box<str>, Timestamp)>;
1504 async fn add_profile_public_key(
1510 &self,
1511 id_tag: &str,
1512 key_id: &str,
1513 public_key: &str,
1514 expires_at: Option<Timestamp>,
1515 ) -> ClResult<()>;
1516 async fn list_stale_profiles(
1527 &self,
1528 max_age_secs: i64,
1529 disable_after_secs: i64,
1530 limit: u32,
1531 ) -> ClResult<Vec<(TnId, Box<str>, Option<Box<str>>)>>;
1532
1533 async fn get_action_id(&self, tn_id: TnId, a_id: u64) -> ClResult<Box<str>>;
1536 async fn list_actions(
1537 &self,
1538 tn_id: TnId,
1539 opts: &ListActionOptions,
1540 ) -> ClResult<Vec<ActionView>>;
1541 async fn list_action_tokens(
1542 &self,
1543 tn_id: TnId,
1544 opts: &ListActionOptions,
1545 ) -> ClResult<Box<[Box<str>]>>;
1546
1547 async fn count_actions_grouped(
1551 &self,
1552 tn_id: TnId,
1553 opts: &ListActionOptions,
1554 group_by: ActionCountGroupBy,
1555 ) -> ClResult<Vec<(Option<String>, i64)>>;
1556
1557 async fn count_actions(&self, tn_id: TnId, opts: &ListActionOptions) -> ClResult<i64>;
1563
1564 async fn set_read_marker(
1571 &self,
1572 tn_id: TnId,
1573 scope: &str,
1574 key: &str,
1575 position: i64,
1576 ) -> ClResult<()>;
1577
1578 async fn auto_track_action(&self, tn_id: TnId, action_id: &str) -> ClResult<()>;
1582
1583 async fn create_action(
1584 &self,
1585 tn_id: TnId,
1586 action: &Action<&str>,
1587 key: Option<&str>,
1588 ) -> ClResult<ActionId<Box<str>>>;
1589
1590 async fn finalize_action(
1591 &self,
1592 tn_id: TnId,
1593 a_id: u64,
1594 action_id: &str,
1595 options: FinalizeActionOptions<'_>,
1596 ) -> ClResult<()>;
1597
1598 async fn create_inbound_action(
1599 &self,
1600 tn_id: TnId,
1601 action_id: &str,
1602 token: &str,
1603 ack_token: Option<&str>,
1604 ) -> ClResult<()>;
1605
1606 async fn get_action_root_id(&self, tn_id: TnId, action_id: &str) -> ClResult<Box<str>>;
1608
1609 async fn get_action_data(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<ActionData>>;
1611
1612 async fn get_action_by_key(
1614 &self,
1615 tn_id: TnId,
1616 action_key: &str,
1617 ) -> ClResult<Option<Action<Box<str>>>>;
1618
1619 async fn store_action_token(&self, tn_id: TnId, action_id: &str, token: &str) -> ClResult<()>;
1621
1622 async fn get_action_token(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<Box<str>>>;
1624
1625 async fn update_action_data(
1627 &self,
1628 tn_id: TnId,
1629 action_id: &str,
1630 opts: &UpdateActionDataOptions,
1631 ) -> ClResult<()>;
1632
1633 async fn update_inbound_action(
1635 &self,
1636 tn_id: TnId,
1637 action_id: &str,
1638 status: Option<char>,
1639 ) -> ClResult<()>;
1640
1641 async fn get_related_action_tokens(
1644 &self,
1645 tn_id: TnId,
1646 aprv_action_id: &str,
1647 ) -> ClResult<Vec<(Box<str>, Box<str>)>>;
1648
1649 async fn get_file_id(&self, tn_id: TnId, f_id: u64) -> ClResult<Box<str>>;
1652 async fn list_files(&self, tn_id: TnId, opts: &ListFileOptions) -> ClResult<Vec<FileView>>;
1653 async fn list_file_variants(
1654 &self,
1655 tn_id: TnId,
1656 file_id: FileId<&str>,
1657 ) -> ClResult<Vec<FileVariant<Box<str>>>>;
1658 async fn list_available_variants(&self, tn_id: TnId, file_id: &str) -> ClResult<Vec<Box<str>>>;
1660 async fn list_referenced_variant_ids(&self, tn_id: TnId) -> ClResult<Vec<Box<str>>>;
1665 async fn is_variant_referenced(&self, tn_id: TnId, variant_id: &str) -> ClResult<bool>;
1671 async fn read_file_variant(
1672 &self,
1673 tn_id: TnId,
1674 variant_id: &str,
1675 ) -> ClResult<FileVariant<Box<str>>>;
1676 async fn read_file_id_by_variant(&self, tn_id: TnId, variant_id: &str) -> ClResult<Box<str>>;
1678 async fn read_f_id_by_file_id(&self, tn_id: TnId, file_id: &str) -> ClResult<u64>;
1680 async fn create_file(&self, tn_id: TnId, opts: CreateFile) -> ClResult<FileId<Box<str>>>;
1681 async fn create_file_variant<'a>(
1682 &'a self,
1683 tn_id: TnId,
1684 f_id: u64,
1685 opts: FileVariant<&'a str>,
1686 ) -> ClResult<&'a str>;
1687 async fn update_file_id(&self, tn_id: TnId, f_id: u64, file_id: &str) -> ClResult<()>;
1688
1689 async fn finalize_file(&self, tn_id: TnId, f_id: u64, file_id: &str) -> ClResult<()>;
1691
1692 async fn list_files_by_parent(
1697 &self,
1698 tn_id: TnId,
1699 parent_id: &str,
1700 before: Timestamp,
1701 ) -> ClResult<Vec<u64>>;
1702
1703 async fn list_referenced_managed_fids(&self, tn_id: TnId) -> ClResult<HashSet<u64>>;
1725
1726 async fn hard_delete_file(&self, tn_id: TnId, f_id: u64) -> ClResult<()>;
1729
1730 async fn list_tasks(&self, opts: ListTaskOptions) -> ClResult<Vec<Task>>;
1733 async fn list_task_ids(&self, kind: &str, keys: &[Box<str>]) -> ClResult<Vec<u64>>;
1734 async fn create_task(
1735 &self,
1736 kind: &'static str,
1737 key: Option<&str>,
1738 input: &str,
1739 deps: &[u64],
1740 ) -> ClResult<u64>;
1741 async fn update_task_finished(&self, task_id: u64, output: &str) -> ClResult<()>;
1742 async fn update_task_error(
1743 &self,
1744 task_id: u64,
1745 output: &str,
1746 next_at: Option<Timestamp>,
1747 ) -> ClResult<()>;
1748
1749 async fn find_task_by_key(&self, key: &str) -> ClResult<Option<Task>>;
1751
1752 async fn update_task(&self, task_id: u64, patch: &TaskPatch) -> ClResult<()>;
1754
1755 async fn find_completed_deps(&self, deps: &[u64]) -> ClResult<Vec<u64>>;
1757
1758 async fn get_profile_info(&self, tn_id: TnId, id_tag: &str) -> ClResult<ProfileData>;
1762
1763 async fn get_action(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<ActionView>>;
1767
1768 async fn get_action_type(&self, tn_id: TnId, action_id: &str) -> ClResult<Option<Box<str>>>;
1770
1771 async fn update_action(
1773 &self,
1774 tn_id: TnId,
1775 action_id: &str,
1776 content: Option<&str>,
1777 attachments: Option<&[&str]>,
1778 ) -> ClResult<()>;
1779
1780 async fn delete_action(&self, tn_id: TnId, action_id: &str) -> ClResult<()>;
1782
1783 async fn delete_file(&self, tn_id: TnId, file_id: &str) -> ClResult<()>;
1787
1788 async fn list_children_by_root(&self, tn_id: TnId, root_id: &str) -> ClResult<Vec<Box<str>>>;
1790
1791 async fn list_settings(
1795 &self,
1796 tn_id: TnId,
1797 prefix: Option<&[String]>,
1798 ) -> ClResult<std::collections::HashMap<String, serde_json::Value>>;
1799
1800 async fn read_setting(&self, tn_id: TnId, name: &str) -> ClResult<Option<serde_json::Value>>;
1802
1803 async fn update_setting(
1805 &self,
1806 tn_id: TnId,
1807 name: &str,
1808 value: Option<serde_json::Value>,
1809 ) -> ClResult<()>;
1810
1811 async fn list_refs(&self, tn_id: TnId, opts: &ListRefsOptions) -> ClResult<Vec<RefData>>;
1815
1816 async fn get_ref(&self, tn_id: TnId, ref_id: &str) -> ClResult<Option<RefData>>;
1818
1819 async fn create_ref(
1821 &self,
1822 tn_id: TnId,
1823 ref_id: &str,
1824 opts: &CreateRefOptions,
1825 ) -> ClResult<RefData>;
1826
1827 async fn delete_ref(&self, tn_id: TnId, ref_id: &str) -> ClResult<()>;
1829
1830 async fn update_ref(
1832 &self,
1833 tn_id: TnId,
1834 ref_id: &str,
1835 opts: &UpdateRefOptions,
1836 ) -> ClResult<RefData>;
1837
1838 async fn use_ref(
1841 &self,
1842 ref_id: &str,
1843 expected_types: &[&str],
1844 ) -> ClResult<(TnId, Box<str>, RefData)>;
1845
1846 async fn validate_ref(
1849 &self,
1850 ref_id: &str,
1851 expected_types: &[&str],
1852 ) -> ClResult<(TnId, Box<str>, RefData)>;
1853
1854 async fn list_tags(
1864 &self,
1865 tn_id: TnId,
1866 prefix: Option<&str>,
1867 with_counts: bool,
1868 limit: Option<u32>,
1869 ) -> ClResult<Vec<TagInfo>>;
1870
1871 async fn add_tag(&self, tn_id: TnId, file_id: &str, tag: &str) -> ClResult<Vec<String>>;
1873
1874 async fn remove_tag(&self, tn_id: TnId, file_id: &str, tag: &str) -> ClResult<Vec<String>>;
1876
1877 async fn update_file_data(
1881 &self,
1882 tn_id: TnId,
1883 file_id: &str,
1884 opts: &UpdateFileOptions,
1885 ) -> ClResult<()>;
1886
1887 async fn read_file(&self, tn_id: TnId, file_id: &str) -> ClResult<Option<FileView>>;
1889
1890 async fn read_file_with_user_data(
1894 &self,
1895 tn_id: TnId,
1896 file_id: &str,
1897 id_tag: &str,
1898 ) -> ClResult<Option<FileView>>;
1899
1900 async fn record_file_access(&self, tn_id: TnId, id_tag: &str, file_id: &str) -> ClResult<()>;
1905
1906 async fn record_file_modification(
1908 &self,
1909 tn_id: TnId,
1910 id_tag: &str,
1911 file_id: &str,
1912 ) -> ClResult<()>;
1913
1914 async fn update_file_user_data(
1923 &self,
1924 tn_id: TnId,
1925 id_tag: &str,
1926 file_id: &str,
1927 pinned: crate::types::Patch<bool>,
1928 starred: crate::types::Patch<bool>,
1929 access_level: crate::types::Patch<char>,
1930 ) -> ClResult<FileUserData>;
1931
1932 async fn get_file_user_data(
1934 &self,
1935 tn_id: TnId,
1936 id_tag: &str,
1937 file_id: &str,
1938 ) -> ClResult<Option<FileUserData>>;
1939
1940 async fn list_push_subscriptions(&self, tn_id: TnId) -> ClResult<Vec<PushSubscription>>;
1948
1949 async fn create_push_subscription(
1955 &self,
1956 tn_id: TnId,
1957 subscription: &PushSubscriptionData,
1958 ) -> ClResult<u64>;
1959
1960 async fn delete_push_subscription(&self, tn_id: TnId, subscription_id: u64) -> ClResult<()>;
1965
1966 async fn create_share_entry(
1971 &self,
1972 tn_id: TnId,
1973 resource_type: char,
1974 resource_id: &str,
1975 created_by: &str,
1976 entry: &CreateShareEntry,
1977 ) -> ClResult<ShareEntry>;
1978
1979 async fn delete_share_entry(&self, tn_id: TnId, id: i64) -> ClResult<()>;
1981
1982 async fn update_share_entry(
1988 &self,
1989 tn_id: TnId,
1990 id: i64,
1991 resource_type: char,
1992 resource_id: &str,
1993 opts: &UpdateShareEntryOptions,
1994 ) -> ClResult<ShareEntry>;
1995
1996 async fn list_share_entries(
1998 &self,
1999 tn_id: TnId,
2000 resource_type: char,
2001 resource_id: &str,
2002 ) -> ClResult<Vec<ShareEntry>>;
2003
2004 async fn list_share_entries_by_subject(
2007 &self,
2008 tn_id: TnId,
2009 subject_type: Option<char>,
2010 subject_id: &str,
2011 ) -> ClResult<Vec<ShareEntry>>;
2012
2013 async fn check_share_access(
2016 &self,
2017 tn_id: TnId,
2018 resource_type: char,
2019 resource_id: &str,
2020 subject_type: char,
2021 subject_id: &str,
2022 ) -> ClResult<Option<char>>;
2023
2024 async fn read_share_entry(&self, tn_id: TnId, id: i64) -> ClResult<Option<ShareEntry>>;
2026
2027 async fn install_app(&self, tn_id: TnId, install: &InstallApp) -> ClResult<()>;
2032
2033 async fn uninstall_app(&self, tn_id: TnId, app_name: &str, publisher_tag: &str)
2035 -> ClResult<()>;
2036
2037 async fn list_installed_apps(
2039 &self,
2040 tn_id: TnId,
2041 search: Option<&str>,
2042 ) -> ClResult<Vec<InstalledApp>>;
2043
2044 async fn get_installed_app(
2046 &self,
2047 tn_id: TnId,
2048 app_name: &str,
2049 publisher_tag: &str,
2050 ) -> ClResult<Option<InstalledApp>>;
2051
2052 async fn create_address_book(
2057 &self,
2058 tn_id: TnId,
2059 name: &str,
2060 description: Option<&str>,
2061 ) -> ClResult<AddressBook>;
2062
2063 async fn list_address_books(&self, tn_id: TnId) -> ClResult<Vec<AddressBook>>;
2065
2066 async fn get_address_book(&self, tn_id: TnId, ab_id: u64) -> ClResult<Option<AddressBook>>;
2068
2069 async fn get_address_book_by_name(
2071 &self,
2072 tn_id: TnId,
2073 name: &str,
2074 ) -> ClResult<Option<AddressBook>>;
2075
2076 async fn update_address_book(
2078 &self,
2079 tn_id: TnId,
2080 ab_id: u64,
2081 patch: &UpdateAddressBookData,
2082 ) -> ClResult<()>;
2083
2084 async fn delete_address_book(&self, tn_id: TnId, ab_id: u64) -> ClResult<()>;
2086
2087 async fn list_contacts(
2090 &self,
2091 tn_id: TnId,
2092 ab_id: Option<u64>,
2093 opts: &ListContactOptions,
2094 ) -> ClResult<Vec<ContactView>>;
2095
2096 async fn get_contact(&self, tn_id: TnId, ab_id: u64, uid: &str) -> ClResult<Option<Contact>>;
2098
2099 async fn upsert_contact(
2102 &self,
2103 tn_id: TnId,
2104 ab_id: u64,
2105 uid: &str,
2106 vcard: &str,
2107 etag: &str,
2108 extracted: &ContactExtracted,
2109 ) -> ClResult<Box<str>>;
2110
2111 async fn delete_contact(&self, tn_id: TnId, ab_id: u64, uid: &str) -> ClResult<()>;
2114
2115 async fn get_contacts_by_uids(
2117 &self,
2118 tn_id: TnId,
2119 ab_id: u64,
2120 uids: &[&str],
2121 ) -> ClResult<Vec<Contact>>;
2122
2123 async fn list_contacts_since(
2129 &self,
2130 tn_id: TnId,
2131 ab_id: u64,
2132 since: Option<Timestamp>,
2133 limit: Option<u32>,
2134 ) -> ClResult<Vec<ContactSyncEntry>>;
2135
2136 async fn list_contacts_by_profile(
2138 &self,
2139 tn_id: TnId,
2140 profile_id_tag: &str,
2141 ) -> ClResult<Vec<Contact>>;
2142
2143 async fn create_calendar(&self, tn_id: TnId, input: &CreateCalendarData) -> ClResult<Calendar>;
2148
2149 async fn list_calendars(&self, tn_id: TnId) -> ClResult<Vec<Calendar>>;
2151
2152 async fn get_calendar(&self, tn_id: TnId, cal_id: u64) -> ClResult<Option<Calendar>>;
2154
2155 async fn get_calendar_by_name(&self, tn_id: TnId, name: &str) -> ClResult<Option<Calendar>>;
2157
2158 async fn update_calendar(
2160 &self,
2161 tn_id: TnId,
2162 cal_id: u64,
2163 patch: &UpdateCalendarData,
2164 ) -> ClResult<()>;
2165
2166 async fn delete_calendar(&self, tn_id: TnId, cal_id: u64) -> ClResult<()>;
2168
2169 async fn list_calendar_objects(
2171 &self,
2172 tn_id: TnId,
2173 cal_id: u64,
2174 opts: &ListCalendarObjectOptions,
2175 ) -> ClResult<Vec<CalendarObjectView>>;
2176
2177 async fn get_calendar_object(
2181 &self,
2182 tn_id: TnId,
2183 cal_id: u64,
2184 uid: &str,
2185 ) -> ClResult<Option<CalendarObject>>;
2186
2187 async fn get_calendar_object_override(
2189 &self,
2190 tn_id: TnId,
2191 cal_id: u64,
2192 uid: &str,
2193 recurrence_id: Timestamp,
2194 ) -> ClResult<Option<CalendarObject>>;
2195
2196 async fn list_calendar_object_overrides(
2198 &self,
2199 tn_id: TnId,
2200 cal_id: u64,
2201 uid: &str,
2202 ) -> ClResult<Vec<CalendarObject>>;
2203
2204 async fn delete_calendar_object_override(
2206 &self,
2207 tn_id: TnId,
2208 cal_id: u64,
2209 uid: &str,
2210 recurrence_id: Timestamp,
2211 ) -> ClResult<()>;
2212
2213 async fn upsert_calendar_object(
2217 &self,
2218 tn_id: TnId,
2219 cal_id: u64,
2220 uid: &str,
2221 ical: &str,
2222 etag: &str,
2223 extracted: &CalendarObjectExtracted,
2224 ) -> ClResult<Box<str>>;
2225
2226 async fn delete_calendar_object(&self, tn_id: TnId, cal_id: u64, uid: &str) -> ClResult<()>;
2229
2230 async fn split_calendar_object_series(
2241 &self,
2242 tn_id: TnId,
2243 cal_id: u64,
2244 master: CalendarObjectWrite<'_>,
2245 tail: CalendarObjectWrite<'_>,
2246 split_at: Timestamp,
2247 ) -> ClResult<(Box<str>, Box<str>)>;
2248
2249 async fn get_calendar_objects_by_uids(
2251 &self,
2252 tn_id: TnId,
2253 cal_id: u64,
2254 uids: &[&str],
2255 ) -> ClResult<Vec<CalendarObject>>;
2256
2257 async fn list_calendar_objects_since(
2260 &self,
2261 tn_id: TnId,
2262 cal_id: u64,
2263 since: Option<Timestamp>,
2264 limit: Option<u32>,
2265 ) -> ClResult<Vec<CalendarObjectSyncEntry>>;
2266
2267 async fn query_calendar_objects_in_range(
2272 &self,
2273 tn_id: TnId,
2274 cal_id: u64,
2275 component: Option<&str>,
2276 start: Option<Timestamp>,
2277 end: Option<Timestamp>,
2278 ) -> ClResult<Vec<CalendarObject>>;
2279}
2280
2281#[cfg(test)]
2282mod tests {
2283 use super::*;
2284 #[test]
2285 fn test_deserialize_list_action_options_with_multiple_statuses() {
2286 let query = "status=C,N&type=POST,REPLY";
2287 let opts: ListActionOptions =
2288 serde_urlencoded::from_str(query).expect("should deserialize");
2289
2290 assert!(opts.status.is_some());
2291 let statuses = opts.status.expect("status should be Some");
2292 assert_eq!(statuses.len(), 2);
2293 assert_eq!(statuses[0].as_str(), "C");
2294 assert_eq!(statuses[1].as_str(), "N");
2295
2296 assert!(opts.typ.is_some());
2297 let types = opts.typ.expect("type should be Some");
2298 assert_eq!(types.len(), 2);
2299 assert_eq!(types[0].as_str(), "POST");
2300 assert_eq!(types[1].as_str(), "REPLY");
2301 }
2302
2303 #[test]
2304 fn test_deserialize_list_action_options_without_status() {
2305 let query = "issuer=alice";
2306 let opts: ListActionOptions =
2307 serde_urlencoded::from_str(query).expect("should deserialize");
2308
2309 assert!(opts.status.is_none());
2310 assert!(opts.typ.is_none());
2311 assert_eq!(opts.issuer.as_deref(), Some("alice"));
2312 }
2313
2314 #[test]
2315 fn test_deserialize_list_action_options_single_status() {
2316 let query = "status=C";
2317 let opts: ListActionOptions =
2318 serde_urlencoded::from_str(query).expect("should deserialize");
2319
2320 assert!(opts.status.is_some());
2321 let statuses = opts.status.expect("status should be Some");
2322 assert_eq!(statuses.len(), 1);
2323 assert_eq!(statuses[0].as_str(), "C");
2324 }
2325
2326 #[test]
2327 fn test_deserialize_list_action_options_audience_type() {
2328 let opts: ListActionOptions = serde_urlencoded::from_str("audienceType=personal")
2329 .expect("should deserialize personal");
2330 assert!(matches!(opts.audience_type, Some(AudienceType::Personal)));
2331
2332 let opts: ListActionOptions = serde_urlencoded::from_str("audienceType=community")
2333 .expect("should deserialize community");
2334 assert!(matches!(opts.audience_type, Some(AudienceType::Community)));
2335
2336 let opts: ListActionOptions =
2337 serde_urlencoded::from_str("issuer=alice").expect("should deserialize");
2338 assert!(opts.audience_type.is_none());
2339
2340 let res: Result<ListActionOptions, _> = serde_urlencoded::from_str("audienceType=garbage");
2341 assert!(res.is_err(), "garbage audienceType should error");
2342 }
2343
2344 #[test]
2345 fn test_deserialize_list_action_options_multi_visibility() {
2346 let opts: ListActionOptions =
2347 serde_urlencoded::from_str("visibility=F,C").expect("should deserialize");
2348 let v = opts.visibility.expect("visibility should be Some");
2349 assert_eq!(v.len(), 2);
2350 assert_eq!(v[0].as_str(), "F");
2351 assert_eq!(v[1].as_str(), "C");
2352
2353 let opts: ListActionOptions =
2354 serde_urlencoded::from_str("visibility=P").expect("should deserialize");
2355 let v = opts.visibility.expect("visibility should be Some");
2356 assert_eq!(v.len(), 1);
2357 assert_eq!(v[0].as_str(), "P");
2358
2359 let opts: ListActionOptions =
2360 serde_urlencoded::from_str("issuer=alice").expect("should deserialize");
2361 assert!(opts.visibility.is_none());
2362 }
2363
2364 #[test]
2365 fn test_deserialize_list_action_options_visibility_with_direct() {
2366 let opts: ListActionOptions =
2367 serde_urlencoded::from_str("visibility=D,F").expect("should deserialize");
2368 let v = opts.visibility.expect("visibility should be Some");
2369 assert_eq!(v.len(), 2);
2370 assert_eq!(v[0].as_str(), "D");
2371 assert_eq!(v[1].as_str(), "F");
2372 }
2373
2374 #[test]
2375 fn test_broken_reason_as_str_matches_serde() {
2376 for reason in [BrokenReason::Deleted, BrokenReason::Revoked] {
2377 let via_serde = serde_json::to_value(reason)
2378 .expect("serialize")
2379 .as_str()
2380 .expect("string variant")
2381 .to_string();
2382 assert_eq!(reason.as_str(), via_serde, "as_str diverged from serde for {:?}", reason);
2383 }
2384 }
2385}
2386
2387