diff options
author | 2021-08-28 10:14:39 -0700 | |
---|---|---|
committer | 2021-08-28 17:14:39 +0000 | |
commit | c9266553610fd48a66048d9169da4703a0c71716 (patch) | |
tree | 0d65a763f646d8b213411328d56b99620123edc2 | |
parent | 4fa6f626a0fc571b0293d63da78ca37b4e359af1 (diff) | |
download | notion-c9266553610fd48a66048d9169da4703a0c71716.tar.gz notion-c9266553610fd48a66048d9169da4703a0c71716.tar.zst notion-c9266553610fd48a66048d9169da4703a0c71716.zip |
Number format parsing bug. Fixes #15 (#16)
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/models.rs | 68 | ||||
-rw-r--r-- | src/models/paging.rs | 4 | ||||
-rw-r--r-- | src/models/properties.rs | 104 | ||||
-rw-r--r-- | src/models/search.rs | 11 | ||||
-rw-r--r-- | src/models/tests/issue_15.json | 89 | ||||
-rw-r--r-- | src/models/text.rs | 36 |
7 files changed, 212 insertions, 102 deletions
@@ -94,7 +94,7 @@ impl NotionApi { } /// Search all pages in notion. - /// Query: can either be a [SearchRequest] or a + /// `query` can either be a [SearchRequest] or a slightly more convenient /// [NotionSearch](models::search::NotionSearch) query. pub async fn search<T: Into<SearchRequest>>( &self, diff --git a/src/models.rs b/src/models.rs index 78ad105..fc31d17 100644 --- a/src/models.rs +++ b/src/models.rs @@ -39,17 +39,17 @@ impl Display for DatabaseId { } /// Represents a Notion Database -/// See https://developers.notion.com/reference/database +/// See <https://developers.notion.com/reference/database> #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Database { /// Unique identifier for the database. - id: DatabaseId, + pub id: DatabaseId, /// Date and time when this database was created. - created_time: DateTime<Utc>, + pub created_time: DateTime<Utc>, /// Date and time when this database was updated. - last_edited_time: DateTime<Utc>, + pub last_edited_time: DateTime<Utc>, /// Name of the database as it appears in Notion. - title: Vec<RichText>, + pub title: Vec<RichText>, /// Schema of properties for the database as they appear in Notion. // // key string @@ -57,7 +57,7 @@ pub struct Database { // // value object // A Property object. - properties: HashMap<String, PropertyConfiguration>, + pub properties: HashMap<String, PropertyConfiguration>, } impl AsIdentifier<DatabaseId> for Database { @@ -75,7 +75,7 @@ impl Database { } } -/// https://developers.notion.com/reference/pagination#responses +/// <https://developers.notion.com/reference/pagination#responses> #[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)] pub struct ListResponse<T> { pub results: Vec<T>, @@ -137,51 +137,51 @@ pub enum Parent { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Properties { #[serde(flatten)] - properties: HashMap<String, PropertyValue>, + pub properties: HashMap<String, PropertyValue>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Page { - id: PageId, + pub id: PageId, /// Date and time when this page was created. - created_time: DateTime<Utc>, + pub created_time: DateTime<Utc>, /// Date and time when this page was updated. - last_edited_time: DateTime<Utc>, + pub last_edited_time: DateTime<Utc>, /// The archived status of the page. - archived: bool, - properties: Properties, - parent: Parent, + pub archived: bool, + pub properties: Properties, + pub parent: Parent, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct BlockCommon { - id: BlockId, - created_time: DateTime<Utc>, - last_edited_time: DateTime<Utc>, - has_children: bool, + pub id: BlockId, + pub created_time: DateTime<Utc>, + pub last_edited_time: DateTime<Utc>, + pub has_children: bool, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TextAndChildren { - text: Vec<RichText>, - children: Option<Vec<Block>>, + pub text: Vec<RichText>, + pub children: Option<Vec<Block>>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Text { - text: Vec<RichText>, + pub text: Vec<RichText>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ToDoFields { - text: Vec<RichText>, - checked: bool, - children: Option<Vec<Block>>, + pub text: Vec<RichText>, + pub checked: bool, + pub children: Option<Vec<Block>>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ChildPageFields { - title: String, + pub title: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -339,19 +339,19 @@ impl UserId { #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct UserCommon { - id: UserId, - name: Option<String>, - avatar_url: Option<String>, + pub id: UserId, + pub name: Option<String>, + pub avatar_url: Option<String>, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct Person { - email: String, + pub email: String, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct Bot { - email: String, + pub email: String, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] @@ -371,7 +371,7 @@ pub enum User { #[cfg(test)] mod tests { - use crate::models::{ListResponse, Page}; + use crate::models::{ListResponse, Object, Page}; #[test] fn deserialize_page() { @@ -383,4 +383,10 @@ mod tests { let _page: ListResponse<Page> = serde_json::from_str(include_str!("models/tests/query_result.json")).unwrap(); } + + #[test] + fn deserialize_number_format() { + let _search_results: ListResponse<Object> = + serde_json::from_str(include_str!("models/tests/issue_15.json")).unwrap(); + } } diff --git a/src/models/paging.rs b/src/models/paging.rs index 31244a2..3b97301 100644 --- a/src/models/paging.rs +++ b/src/models/paging.rs @@ -7,7 +7,7 @@ pub struct PagingCursor(String); #[derive(Serialize, Debug, Eq, PartialEq, Default)] pub struct Paging { #[serde(skip_serializing_if = "Option::is_none")] - start_cursor: Option<PagingCursor>, + pub start_cursor: Option<PagingCursor>, #[serde(skip_serializing_if = "Option::is_none")] - page_size: Option<u8>, + pub page_size: Option<u8>, } diff --git a/src/models/properties.rs b/src/models/properties.rs index 22689e9..b3948b4 100644 --- a/src/models/properties.rs +++ b/src/models/properties.rs @@ -9,8 +9,7 @@ use super::{DateTime, Number, Utc}; pub struct PropertyId(String); /// How the number is displayed in Notion. -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)] -#[serde(tag = "type")] +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone, Hash)] #[serde(rename_all = "snake_case")] pub enum NumberFormat { Number, @@ -26,6 +25,11 @@ pub enum NumberFormat { Yuan, } +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)] +pub struct NumberDetails { + pub format: NumberFormat, +} + #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)] #[serde(transparent)] pub struct SelectOptionId(String); @@ -47,37 +51,37 @@ pub enum Color { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SelectOption { - name: String, - id: SelectOptionId, - color: Color, + pub name: String, + pub id: SelectOptionId, + pub color: Color, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Select { /// Sorted list of options available for this property. - options: Vec<SelectOption>, + pub options: Vec<SelectOption>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Formula { /// Formula to evaluate for this property - expression: String, + pub expression: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Relation { /// The database this relation refers to. /// New linked pages must belong to this database in order to be valid. - database_id: DatabaseId, + pub database_id: DatabaseId, /// By default, relations are formed as two synced properties across databases: /// if you make a change to one property, it updates the synced property at the same time. /// `synced_property_name` refers to the name of the property in the related database. - synced_property_name: Option<String>, + pub synced_property_name: Option<String>, /// By default, relations are formed as two synced properties across databases: /// if you make a change to one property, it updates the synced property at the same time. /// `synced_property_id` refers to the id of the property in the related database. /// This is usually a short string of random letters and symbols. - synced_property_id: Option<PropertyId>, + pub synced_property_id: Option<PropertyId>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)] @@ -101,17 +105,17 @@ pub enum RollupFunction { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Rollup { /// The name of the relation property this property is responsible for rolling up. - relation_property_name: String, + pub relation_property_name: String, /// The id of the relation property this property is responsible for rolling up. - relation_property_id: PropertyId, + pub relation_property_id: PropertyId, /// The name of the property of the pages in the related database /// that is used as an input to `function`. - rollup_property_name: String, + pub rollup_property_name: String, /// The id of the property of the pages in the related database /// that is used as an input to `function`. - rollup_property_id: String, + pub rollup_property_id: String, /// The function that is evaluated for every page in the relation of the rollup. - function: RollupFunction, + pub function: RollupFunction, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -119,80 +123,80 @@ pub struct Rollup { #[serde(rename_all = "snake_case")] pub enum PropertyConfiguration { /// Represents the special Title property required on every database. - /// See https://developers.notion.com/reference/database#title-configuration + /// See <https://developers.notion.com/reference/database#title-configuration> Title { id: PropertyId }, /// Represents a Text property - /// https://developers.notion.com/reference/database#text-configuration + /// <https://developers.notion.com/reference/database#text-configuration> #[serde(rename = "rich_text")] Text { id: PropertyId }, /// Represents a Number Property - /// See https://developers.notion.com/reference/database#number-configuration + /// See <https://developers.notion.com/reference/database#number-configuration> Number { id: PropertyId, /// How the number is displayed in Notion. - format: NumberFormat, + number: NumberDetails, }, /// Represents a Select Property - /// See https://developers.notion.com/reference/database#select-configuration + /// See <https://developers.notion.com/reference/database#select-configuration> Select { id: PropertyId, select: Select }, /// Represents a Multi-select Property - /// See https://developers.notion.com/reference/database#multi-select-configuration + /// See <https://developers.notion.com/reference/database#multi-select-configuration> MultiSelect { id: PropertyId, multi_select: Select, }, /// Represents a Date Property - /// See https://developers.notion.com/reference/database#date-configuration + /// See <https://developers.notion.com/reference/database#date-configuration> Date { id: PropertyId }, /// Represents a People Property - /// See https://developers.notion.com/reference/database#people-configuration + /// See <https://developers.notion.com/reference/database#people-configuration> People { id: PropertyId }, /// Represents a File Property - /// See https://developers.notion.com/reference/database#file-configuration + /// See <https://developers.notion.com/reference/database#file-configuration> // Todo: File a bug with notion // Documentation issue: docs claim type name is `file` but it is in fact `files` Files { id: PropertyId }, /// Represents a Checkbox Property - /// See https://developers.notion.com/reference/database#checkbox-configuration + /// See <https://developers.notion.com/reference/database#checkbox-configuration> Checkbox { id: PropertyId }, /// Represents a URL Property - /// See https://developers.notion.com/reference/database#url-configuration + /// See <https://developers.notion.com/reference/database#url-configuration> Url { id: PropertyId }, /// Represents a Email Property - /// See https://developers.notion.com/reference/database#email-configuration + /// See <https://developers.notion.com/reference/database#email-configuration> Email { id: PropertyId }, /// Represents a Phone number Property - /// See https://developers.notion.com/reference/database#phone-number-configuration + /// See <https://developers.notion.com/reference/database#phone-number-configuration> PhoneNumber { id: PropertyId }, - /// See https://developers.notion.com/reference/database#formula-configuration + /// See <https://developers.notion.com/reference/database#formula-configuration> Formula { id: PropertyId, formula: Formula }, - /// See https://developers.notion.com/reference/database#relation-configuration + /// See <https://developers.notion.com/reference/database#relation-configuration> Relation { id: PropertyId, relation: Relation }, - /// See https://developers.notion.com/reference/database#rollup-configuration + /// See <https://developers.notion.com/reference/database#rollup-configuration> Rollup { id: PropertyId, rollup: Rollup }, - /// See https://developers.notion.com/reference/database#created-time-configuration + /// See <https://developers.notion.com/reference/database#created-time-configuration> CreatedTime { id: PropertyId }, - /// See https://developers.notion.com/reference/database#created-by-configuration + /// See <https://developers.notion.com/reference/database#created-by-configuration> CreatedBy { id: PropertyId }, - /// See https://developers.notion.com/reference/database#last-edited-time-configuration + /// See <https://developers.notion.com/reference/database#last-edited-time-configuration> LastEditTime { id: PropertyId }, - /// See https://developers.notion.com/reference/database#last-edited-by-configuration + /// See <https://developers.notion.com/reference/database#last-edited-by-configuration> LastEditBy { id: PropertyId }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SelectedValue { - id: SelectOptionId, - name: String, - color: Color, + pub id: SelectOptionId, + pub name: String, + pub color: Color, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct DateValue { // Todo: Will this work with dates (without time)? // does there need to be an enum of Date|DateTime? - start: DateTime<Utc>, - end: Option<DateTime<Utc>>, + pub start: DateTime<Utc>, + pub end: Option<DateTime<Utc>>, } /// Formula property value objects represent the result of evaluating a formula @@ -212,7 +216,7 @@ pub enum FormulaResultValue { /// with a string value (UUIDv4) corresponding to a page ID in another database. #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct RelationValue { - id: PageId, + pub id: PageId, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -228,32 +232,32 @@ pub enum RollupValue { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct FileReference { - name: String, - url: String, - mime_type: String, + pub name: String, + pub url: String, + pub mime_type: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum PropertyValue { - // https://developers.notion.com/reference/page#title-property-values + // <https://developers.notion.com/reference/page#title-property-values> Title { id: PropertyId, title: Vec<RichText>, }, - /// https://developers.notion.com/reference/page#rich-text-property-values + /// <https://developers.notion.com/reference/page#rich-text-property-values> #[serde(rename = "rich_text")] Text { id: PropertyId, rich_text: Vec<RichText>, }, - /// https://developers.notion.com/reference/page#number-property-values + /// <https://developers.notion.com/reference/page#number-property-values> Number { id: PropertyId, number: Number, }, - /// https://developers.notion.com/reference/page#select-property-values + /// <https://developers.notion.com/reference/page#select-property-values> Select { id: PropertyId, select: SelectedValue, @@ -266,12 +270,12 @@ pub enum PropertyValue { id: PropertyId, date: DateValue, }, - /// https://developers.notion.com/reference/page#formula-property-values + /// <https://developers.notion.com/reference/page#formula-property-values> Formula { id: PropertyId, formula: FormulaResultValue, }, - /// https://developers.notion.com/reference/page#relation-property-values + /// <https://developers.notion.com/reference/page#relation-property-values> Relation { id: PropertyId, relation: RelationValue, diff --git a/src/models/search.rs b/src/models/search.rs index ffcac1d..aa2f62e 100644 --- a/src/models/search.rs +++ b/src/models/search.rs @@ -299,13 +299,24 @@ pub struct DatabaseQuery { #[derive(Debug, Eq, PartialEq)] pub enum NotionSearch { + /// When supplied, limits which pages are returned by comparing the query to the page title. Query(String), + /// When supplied, sorts the results based on the provided criteria. + /// + /// Limitation: Currently only a single sort is allowed and is limited to `last_edited_time` Sort { timestamp: SortTimestamp, direction: SortDirection, }, + /// When supplied, filters the results based on the provided criteria. + /// + /// Limitation: Currently the only filter allowed is `object` which will filter by type of object (either page or database) Filter { + /// The name of the property to filter by. + /// Currently the only property you can filter by is the `object` type. property: FilterProperty, + /// The value of the property to filter the results by. + /// Possible values for object type include `page` or `database`. value: FilterValue, }, } diff --git a/src/models/tests/issue_15.json b/src/models/tests/issue_15.json new file mode 100644 index 0000000..7ca0615 --- /dev/null +++ b/src/models/tests/issue_15.json @@ -0,0 +1,89 @@ +{ + "object": "list", + "results": [ + { + "object": "database", + "id": "58be2827-5ca0-4cc4-85a8-ff656911df67", + "created_time": "2021-03-07T19:20:00.000Z", + "last_edited_time": "2021-07-11T22:04:00.000Z", + "title": [ + { + "type": "text", + "text": { "content": "Movie Collection", "link": null }, + "annotations": { + "bold": false, + "italic": false, + "strikethrough": false, + "underline": false, + "code": false, + "color": "default" + }, + "plain_text": "Movie Collection", + "href": null + } + ], + "properties": { + "Watched": { "id": "<dji", "type": "checkbox", "checkbox": {} }, + "Cover": { "id": "VWBk", "type": "files", "files": {} }, + "Type": { + "id": "]iu{", + "type": "select", + "select": { + "options": [ + { + "id": "522ab335-108c-4a92-a2d6-0aeee7b946c8", + "name": "Blu-Ray", + "color": "blue" + }, + { + "id": "12f11180-47bd-4c36-abb8-c84c35ade60c", + "name": "Digital", + "color": "green" + } + ] + } + }, + "Year": { + "id": "jwIv", + "type": "number", + "number": { "format": "number" } + }, + "Director": { + "id": "~psh", + "type": "select", + "select": { + "options": [ + { + "id": "d1023a7a-52af-4c2f-aabf-cac75b59e9bd", + "name": "Hirozaku Kore-eda", + "color": "yellow" + }, + { + "id": "45bd4057-eddc-4bf2-be59-a693f4f81f05", + "name": "Hayao Miyazaki", + "color": "pink" + }, + { + "id": "a1a2896b-26f0-410b-8205-fda67c9edb99", + "name": "Doug Liman", + "color": "orange" + }, + { + "id": "f9854b2d-b913-454f-b18c-ce312fa1d9e4", + "name": "Steven Soderbergh", + "color": "green" + } + ] + } + }, + "Title": { "id": "title", "type": "title", "title": {} } + }, + "parent": { + "type": "page_id", + "page_id": "2ffcd525-17b1-4606-93ff-e367eade9e66" + } + } + ], + "next_cursor": null, + "has_more": false +} diff --git a/src/models/text.rs b/src/models/text.rs index f7ea2b6..b960b6d 100644 --- a/src/models/text.rs +++ b/src/models/text.rs @@ -25,35 +25,35 @@ pub enum TextColor { } /// Rich text annotations -/// See https://developers.notion.com/reference/rich-text#annotations +/// See <https://developers.notion.com/reference/rich-text#annotations> #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] -struct Annotations { - bold: Option<bool>, - code: Option<bool>, - color: Option<TextColor>, - italic: Option<bool>, - strikethrough: Option<bool>, - underline: Option<bool>, +pub struct Annotations { + pub bold: Option<bool>, + pub code: Option<bool>, + pub color: Option<TextColor>, + pub italic: Option<bool>, + pub strikethrough: Option<bool>, + pub underline: Option<bool>, } /// Properties common on all rich text objects -/// See https://developers.notion.com/reference/rich-text#all-rich-text +/// See <https://developers.notion.com/reference/rich-text#all-rich-text> #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct RichTextCommon { - plain_text: String, - href: Option<String>, - annotations: Option<Annotations>, + pub plain_text: String, + pub href: Option<String>, + pub annotations: Option<Annotations>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct Link { - url: String, + pub url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Text { - content: String, - link: Option<String>, + pub content: String, + pub link: Option<String>, } /// Rich text objects contain data for displaying formatted text, mentions, and equations. @@ -64,18 +64,18 @@ pub struct Text { #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum RichText { - /// See https://developers.notion.com/reference/rich-text#text-objects + /// See <https://developers.notion.com/reference/rich-text#text-objects> Text { #[serde(flatten)] rich_text: RichTextCommon, text: Text, }, - /// See https://developers.notion.com/reference/rich-text#mention-objects + /// See <https://developers.notion.com/reference/rich-text#mention-objects> Mention { #[serde(flatten)] rich_text: RichTextCommon, }, - /// See https://developers.notion.com/reference/rich-text#equation-objects + /// See <https://developers.notion.com/reference/rich-text#equation-objects> Equation { #[serde(flatten)] rich_text: RichTextCommon, |