simple_notion/
notion_data_base.rs

1use std::any::TypeId;
2
3pub type DataBaseElement = (String, json::JsonValue);
4
5#[derive(Debug, Clone, Default)]
6pub struct NotionRelation {
7    pub ids: Vec<String>,
8    pub has_more: bool,
9}
10
11impl NotionRelation {
12    pub fn new(ids: Vec<String>, has_more: bool) -> Self {
13        Self {
14            ids,
15            has_more,
16        }
17    }
18}
19
20#[derive(Debug, Clone, Default)]
21pub struct NotionFormula {
22    pub type_name: String,
23    pub result_str: String,
24    pub result_number: f64,
25}
26
27impl NotionFormula {
28    pub fn new(type_name: String, result_str: String, result_number: f64) -> Self {
29        Self {
30            type_name,
31            result_str,
32            result_number,
33        }
34    }
35    
36    pub fn get_type_id(&self) -> TypeId {
37        if self.result_str.is_empty() {
38            TypeId::of::<f64>()
39        } else {
40            TypeId::of::<String>()
41        }
42    }
43}
44
45#[derive(Debug, Clone, Default)]
46pub struct NotionDate {
47    pub start: Option<String>,
48    pub end: Option<String>,
49    pub time_zone: Option<String>,
50}
51
52impl NotionDate {
53    pub fn new(start: Option<String>, end: Option<String>, time_zone: Option<String>) -> Self {
54        Self {
55            start,
56            end,
57            time_zone,
58        }
59    }
60}
61
62#[derive(Debug, Clone)]
63pub struct NotionFile {
64    pub name: String,
65    pub url: String
66}
67
68impl NotionFile {
69    pub fn new(name: String, url: String) -> Self {
70        Self {
71            name,
72            url,
73        }
74    }
75}
76
77#[derive(Debug, Clone)]
78pub enum DataType {
79    Title(String),
80    URL(String),
81    Text(String),
82    Number(f64),
83    Files(Vec<NotionFile>),
84    Select(String),
85    MultiSelect(Vec<String>),
86    CheckBox(bool),
87    EMail(String),
88    Status(String),
89    People(Vec<String>),
90    Date(NotionDate),
91    CreatedBy(String),
92    Formula(NotionFormula),
93    PhoneNumber(String),
94    Relation(NotionRelation),
95    Rollup(Vec<json::JsonValue>),
96    CreatedTime(String),
97    LastEditedTime(String),
98    LastEditedBy(String),
99    Uknown,
100    /// Null & return the type-name of the element
101    Null(String),
102}
103
104impl DataType {
105    pub fn to_json(&self, property_name: &str) -> String {
106        match self {
107            DataType::Title(_title) => {
108                let object = json::JsonValue::new_object();
109
110                format!("\"{}\": {}", property_name, object.dump())
111            }
112            DataType::Number(number) => {
113                format!("\"{}\": {{ \"{}\": {} }}", property_name, crate::non_magic::notion::NOTION_TYPE_NUMBER, number)
114            }
115            _ => String::new(),
116        }
117    }
118}
119
120pub struct NotionDataBase {
121    content: Vec<Vec<DataBaseElement>>,
122}
123
124impl NotionDataBase {
125    pub fn new(content: Vec<Vec<DataBaseElement>>) -> Self {
126        Self { content }
127    }
128    
129    pub fn get_line_count(&self) -> usize {
130        self.content.len()
131    }
132    
133    pub fn get_column_count(&self) -> usize {
134        match self.content.first() {
135            Some(first) => {
136                first.len()
137            }
138            None => 0,
139        }
140    }
141    
142    /// Return the first element of a line
143    pub fn get_first_at(&self, line: usize) -> Option<DataBaseElement> {
144        self.get_at(line, 0)
145    }
146    
147    /// Return the last element of a line
148    #[deprecated(note="Notion not follow any logic in data base index")]
149    pub fn get_last_at(&self, line: usize) -> Option<DataBaseElement> {
150        self.get_at(line, self.get_column_count() - 1)
151    }
152    
153    /// Get an element of the data base using line and column index
154    pub fn get_at(&self, mut line: usize, mut column: usize) -> Option<DataBaseElement> {
155        line = (self.get_line_count() as i32 - 1_i32 - line as i32) as usize;
156        column = (self.get_column_count() as i32 - 1_i32 - column as i32) as usize;
157        
158        match self.content.get(line) {
159            Some(value) => {
160                match value.get(column) {
161                    Some(value) => {
162                        Some(value.clone())
163                    }
164                    None => None,
165                }
166            }
167            None => None,
168        } 
169    }
170    
171    pub fn get(&self, parser: &crate::parser::NotionResponseParser, line: &str, column_name: &str) -> Option<DataBaseElement> {
172        for table_line in self.content.iter() {
173            let mut name = String::new();
174            match parser.parse_element(table_line.last().unwrap().1.clone()) {
175                DataType::Title(title) => {
176                    name = title;
177                }
178                _ => (),   
179            }
180            if name == line {
181                for column in table_line {
182                    if column.0 == column_name {
183                        return Some(column.clone()); 
184                    }
185                }
186            }
187        }
188        None
189    }
190
191    /// Return the list of all the titles content as Vec<String>
192    pub fn get_line_list(&self, parser: &crate::parser::NotionResponseParser) -> Vec<String> {
193        let mut result = Vec::<String>::new();
194
195        for table_line in self.content.iter() {
196            let mut name = String::new();
197            match parser.parse_element(table_line.last().unwrap().1.clone()) {
198                DataType::Title(title) => {
199                    name = title;
200                }
201                _ => (),
202            }
203
204            result.push(name);
205        }
206
207        result
208    }
209
210    /// Return the list of all the columns names as Vec<String>
211    pub fn get_column_list(&self) -> Vec<String> {
212        let mut result = Vec::<String>::new();
213
214        match self.content.first() {
215            Some(first) => {
216                for column in first {
217                    result.push(column.0.clone());
218                }
219            }
220            None => (),
221        }
222
223        result
224    }
225
226    /// Return the full table parsed
227    pub fn get_all(&self, parser: &crate::parser::NotionResponseParser) -> Vec<Vec<DataType>> {
228        let mut result = Vec::<Vec<DataType>>::new();
229
230        let lines = self.get_line_list(&parser);
231        let columns = self.get_column_list();
232
233        for line in lines.iter() {
234            let mut out = Vec::<DataType>::new();
235            for column in columns.iter() {
236                match self.get(&parser, line, column) {
237                    Some(value) => {
238                        out.push(parser.parse_element(value.1));
239                    }
240                    None => (),
241                }
242            }
243            result.push(out);
244        }
245
246        result
247    }
248}