notion_async_api/
object.rs1use std::collections::BTreeMap;
2use std::fmt::Display;
3
4use chrono::{DateTime, Utc};
5use monostate::MustBe;
6use serde::{Deserialize, Serialize};
7use serde_with::serde_as;
8use thiserror::Error;
9
10use crate::misc::Unquotes;
11use crate::user::User;
12
13pub trait Object: Send {
14 fn id(&self) -> &str;
15 fn object_type(&self) -> ObjectType;
16}
17
18#[serde_as]
27#[derive(Serialize, Deserialize, Debug, Clone)]
28pub struct ObjectCommon {
29 pub id: String,
32 pub parent: Parent,
33
34 pub created_time: DateTime<Utc>,
35 pub created_by: User,
36 pub last_edited_time: DateTime<Utc>,
37 pub last_edited_by: User,
38
39 pub archived: bool,
40 pub in_trash: bool,
41}
42
43impl ObjectCommon {
44 pub fn parent_type(&self) -> ParentType {
45 self.parent.r#type()
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case")]
51pub enum ObjectType {
52 Block,
53 Page,
54 Database,
55 User,
56 Comment,
57 List,
58}
59
60impl Display for ObjectType {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 let s = match self {
63 ObjectType::Block => "block",
64 ObjectType::Page => "page",
65 ObjectType::Database => "database",
66 ObjectType::User => "user",
67 ObjectType::Comment => "comment",
68 ObjectType::List => "list",
69 };
70 s.fmt(f)
71 }
72}
73
74#[derive(Debug, Error)]
75#[error("UnsupportObjectError({0})")]
76pub struct UnsupportObjectError(String);
77
78#[allow(unused)]
79#[derive(Deserialize, Debug, Clone)]
80pub struct ObjectList<T> {
81 object: ObjectType, pub results: Vec<T>,
83
84 #[serde(rename = "type")]
85 ttype: String,
86
87 #[serde(skip)]
88 pub start_index: usize,
89
90 #[serde(flatten)]
91 next_page_info: NextPageInfo,
92}
93
94#[derive(Deserialize, Debug, Clone)]
96struct NextPageInfo {
97 next_cursor: Option<String>,
98 has_more: bool,
99}
100
101pub trait NextCursor {
102 fn next_cursor(&self) -> Option<&str>;
103}
104
105impl<T> NextCursor for ObjectList<T> {
106 fn next_cursor(&self) -> Option<&str> {
107 if !self.next_page_info.has_more {
108 None
109 } else {
110 self.next_page_info.next_cursor.as_deref()
111 }
112 }
113}
114
115#[derive(Serialize, Deserialize, Debug, Clone)]
117#[serde(untagged)]
118pub enum Parent {
119 Block { block_id: String },
120 Page { page_id: String },
121 Database { database_id: String },
122 Workspace { workspace: MustBe!(true) },
123}
124
125impl Parent {
126 pub fn id(&self) -> &str {
127 match self {
128 Parent::Block { block_id } => block_id,
129 Parent::Page { page_id } => page_id,
130 Parent::Database { database_id } => database_id,
131 Parent::Workspace { workspace: _ } => "workspace",
132 }
133 }
134
135 pub fn r#type(&self) -> ParentType {
136 match self {
137 Parent::Block { block_id: _ } => ParentType::BlockId,
138 Parent::Page { page_id: _ } => ParentType::PageId,
139 Parent::Database { database_id: _ } => ParentType::DatabaseId,
140 Parent::Workspace { workspace: _ } => ParentType::Workspace,
141 }
142 }
143
144 pub fn workspace() -> Self {
145 Self::Workspace {
146 workspace: MustBe!(true),
147 }
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
152#[serde(rename_all = "snake_case")]
153pub enum ParentType {
154 DatabaseId,
155 PageId,
156 BlockId,
157 Workspace,
158}
159
160impl Display for ParentType {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 let s = serde_json::to_string(self).unwrap();
163 s.unquotes().fmt(f)
164 }
165}
166
167#[derive(Debug, PartialEq, Eq)]
168pub struct ImpossibleParseError;
169
170impl Display for ImpossibleParseError {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 "ImpossibleParseError".fmt(f)
173 }
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct JsonObject {
178 #[serde(flatten)]
179 pub map: BTreeMap<String, serde_json::Value>,
180}
181
182impl Display for JsonObject {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 let s = serde_json::to_string(self).unwrap();
185 s.unquotes().fmt(f)
186 }
187}