use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use crate::ids::{AsIdentifier, BlockId, DatabaseId, PageId}; use crate::models::text::{RichText, TextColor}; use crate::models::users::UserCommon; mod tests; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct BlockCommon { pub id: BlockId, pub created_time: DateTime, pub last_edited_time: DateTime, pub has_children: bool, pub created_by: UserCommon, pub last_edited_by: UserCommon, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TextAndChildren { pub rich_text: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub children: Option>, pub color: TextColor, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Text { pub rich_text: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct InternalFileObject { url: String, expiry_time: DateTime, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ExternalFileObject { url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum FileOrEmojiObject { Emoji { emoji: String }, File { file: InternalFileObject }, External { external: ExternalFileObject }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum FileObject { File { file: InternalFileObject }, External { external: ExternalFileObject }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Callout { pub rich_text: Vec, pub icon: FileOrEmojiObject, pub color: TextColor, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ToDoFields { pub rich_text: Vec, pub checked: bool, #[serde(skip_serializing_if = "Option::is_none")] pub children: Option>, pub color: TextColor, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ChildPageFields { pub title: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ChildDatabaseFields { pub title: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct EmbedFields { pub url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct BookmarkFields { pub url: String, pub caption: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(rename_all = "lowercase")] pub enum CodeLanguage { Abap, Arduino, Bash, Basic, C, Clojure, Coffeescript, #[serde(rename = "c++")] CPlusPlus, #[serde(rename = "c#")] CSharp, Css, Dart, Diff, Docker, Elixir, Elm, Erlang, Flow, Fortran, #[serde(rename = "f#")] FSharp, Gherkin, Glsl, Go, Graphql, Groovy, Haskell, Html, Java, Javascript, Json, Julia, Kotlin, Latex, Less, Lisp, Livescript, Lua, Makefile, Markdown, Markup, Matlab, Mermaid, Nix, #[serde(rename = "objective-c")] ObjectiveC, Ocaml, Pascal, Perl, Php, #[serde(rename = "plain text")] PlainText, Powershell, Prolog, Protobuf, Python, R, Reason, Ruby, Rust, Sass, Scala, Scheme, Scss, Shell, Sql, Swift, Typescript, #[serde(rename = "vb.net")] VbNet, Verilog, Vhdl, #[serde(rename = "visual basic")] VisualBasic, Webassembly, Xml, Yaml, #[serde(rename = "java/c/c++/c#")] JavaCAndCPlusPlusAndCSharp, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct CodeFields { pub rich_text: Vec, pub caption: Vec, pub language: CodeLanguage, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Equation { pub expression: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TableOfContents { pub color: TextColor, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ColumnListFields { pub children: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ColumnFields { pub children: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct LinkPreviewFields { pub url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TemplateFields { pub rich_text: Vec, pub children: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum LinkToPageFields { PageId { page_id: PageId }, DatabaseId { database_id: DatabaseId }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SyncedFromObject { pub block_id: BlockId, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SyncedBlockFields { pub synced_from: Option, pub children: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TableFields { pub table_width: u64, pub has_column_header: bool, pub has_row_header: bool, pub children: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TableRowFields { pub cells: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum Block { Paragraph { #[serde(flatten)] common: BlockCommon, paragraph: TextAndChildren, }, #[serde(rename = "heading_1")] Heading1 { #[serde(flatten)] common: BlockCommon, heading_1: Text, }, #[serde(rename = "heading_2")] Heading2 { #[serde(flatten)] common: BlockCommon, heading_2: Text, }, #[serde(rename = "heading_3")] Heading3 { #[serde(flatten)] common: BlockCommon, heading_3: Text, }, Callout { #[serde(flatten)] common: BlockCommon, callout: Callout, }, Quote { #[serde(flatten)] common: BlockCommon, quote: TextAndChildren, }, BulletedListItem { #[serde(flatten)] common: BlockCommon, bulleted_list_item: TextAndChildren, }, NumberedListItem { #[serde(flatten)] common: BlockCommon, numbered_list_item: TextAndChildren, }, ToDo { #[serde(flatten)] common: BlockCommon, to_do: ToDoFields, }, Toggle { #[serde(flatten)] common: BlockCommon, toggle: TextAndChildren, }, Code { #[serde(flatten)] common: BlockCommon, code: CodeFields, }, ChildPage { #[serde(flatten)] common: BlockCommon, child_page: ChildPageFields, }, ChildDatabase { #[serde(flatten)] common: BlockCommon, child_database: ChildDatabaseFields, }, Embed { #[serde(flatten)] common: BlockCommon, embed: EmbedFields, }, Image { #[serde(flatten)] common: BlockCommon, image: FileObject, }, Video { #[serde(flatten)] common: BlockCommon, video: FileObject, }, File { #[serde(flatten)] common: BlockCommon, file: FileObject, caption: Text, }, Pdf { #[serde(flatten)] common: BlockCommon, pdf: FileObject, }, Bookmark { #[serde(flatten)] common: BlockCommon, bookmark: BookmarkFields, }, Equation { #[serde(flatten)] common: BlockCommon, equation: Equation, }, Divider { #[serde(flatten)] common: BlockCommon, }, TableOfContents { #[serde(flatten)] common: BlockCommon, table_of_contents: TableOfContents, }, Breadcrumb { #[serde(flatten)] common: BlockCommon, }, ColumnList { #[serde(flatten)] common: BlockCommon, column_list: ColumnListFields, }, Column { #[serde(flatten)] common: BlockCommon, column: ColumnFields, }, LinkPreview { #[serde(flatten)] common: BlockCommon, link_preview: LinkPreviewFields, }, Template { #[serde(flatten)] common: BlockCommon, template: TemplateFields, }, LinkToPage { #[serde(flatten)] common: BlockCommon, link_to_page: LinkToPageFields, }, Table { #[serde(flatten)] common: BlockCommon, table: TableFields, }, SyncedBlock { #[serde(flatten)] common: BlockCommon, synced_block: SyncedBlockFields, }, TableRow { #[serde(flatten)] common: BlockCommon, table_row: TableRowFields, }, Unsupported { #[serde(flatten)] common: BlockCommon, }, #[serde(other)] Unknown, } impl AsIdentifier for Block { fn as_id(&self) -> &BlockId { use Block::*; match self { Paragraph { common, .. } | Heading1 { common, .. } | Heading2 { common, .. } | Heading3 { common, .. } | Callout { common, .. } | Quote { common, .. } | BulletedListItem { common, .. } | NumberedListItem { common, .. } | ToDo { common, .. } | Toggle { common, .. } | Code { common, .. } | ChildPage { common, .. } | ChildDatabase { common, .. } | Embed { common, .. } | Image { common, .. } | Video { common, .. } | File { common, .. } | Pdf { common, .. } | Bookmark { common, .. } | Equation { common, .. } | Divider { common, .. } | TableOfContents { common, .. } | Breadcrumb { common, .. } | ColumnList { common, .. } | Column { common, .. } | LinkPreview { common, .. } | Template { common, .. } | LinkToPage { common, .. } | SyncedBlock { common, .. } | Table { common, .. } | TableRow { common, .. } | Unsupported { common, .. } => &common.id, Unknown => { panic!("Trying to reference identifier for unknown block!") } } } } impl Into for Block { fn into(self) -> CreateBlock { match self { Block::Paragraph { paragraph, .. } => CreateBlock::Paragraph { paragraph }, Block::Heading1 { heading_1, .. } => CreateBlock::Heading1 { heading_1 }, Block::Heading2 { heading_2, .. } => CreateBlock::Heading2 { heading_2 }, Block::Heading3 { heading_3, .. } => CreateBlock::Heading3 { heading_3 }, Block::Callout { callout, .. } => CreateBlock::Callout { callout }, Block::Quote { quote, .. } => CreateBlock::Quote { quote }, Block::BulletedListItem { bulleted_list_item, .. } => CreateBlock::BulletedListItem { bulleted_list_item }, Block::NumberedListItem { numbered_list_item, .. } => CreateBlock::NumberedListItem { numbered_list_item }, Block::ToDo { to_do, .. } => CreateBlock::ToDo { to_do }, Block::Toggle { toggle, .. } => CreateBlock::Toggle { toggle }, Block::Code { code, .. } => CreateBlock::Code { code }, Block::ChildPage { child_page, .. } => CreateBlock::ChildPage { child_page }, Block::ChildDatabase { child_database, .. } => CreateBlock::ChildDatabase { child_database }, Block::Embed { embed, .. } => CreateBlock::Embed { embed }, Block::Image { image, .. } => CreateBlock::Image { image }, Block::Video { video, .. } => CreateBlock::Video { video }, Block::File { file, caption, .. } => CreateBlock::File { file, caption }, Block::Pdf { pdf, .. } => CreateBlock::Pdf { pdf }, Block::Bookmark { bookmark, .. } => CreateBlock::Bookmark { bookmark }, Block::Equation { equation, .. } => CreateBlock::Equation { equation }, Block::Divider { .. } => CreateBlock::Divider {}, Block::TableOfContents { table_of_contents, .. } => CreateBlock::TableOfContents { table_of_contents }, Block::Breadcrumb { .. } => CreateBlock::Breadcrumb {}, Block::ColumnList { column_list, .. } => CreateBlock::ColumnList { column_list }, Block::Column { column, .. } => CreateBlock::Column { column }, Block::LinkPreview { link_preview, .. } => CreateBlock::LinkPreview { link_preview }, Block::Template { template, .. } => CreateBlock::Template { template }, Block::LinkToPage { link_to_page, .. } => CreateBlock::LinkToPage { link_to_page }, Block::Table { table, .. } => CreateBlock::Table { table }, Block::SyncedBlock { synced_block, .. } => CreateBlock::SyncedBlock { synced_block }, Block::TableRow { table_row, .. } => CreateBlock::TableRow { table_row }, Block::Unsupported { .. } => CreateBlock::Unsupported, Block::Unknown => CreateBlock::Unknown, } } } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum CreateBlock { Paragraph { paragraph: TextAndChildren, }, #[serde(rename = "heading_1")] Heading1 { heading_1: Text, }, #[serde(rename = "heading_2")] Heading2 { heading_2: Text, }, #[serde(rename = "heading_3")] Heading3 { heading_3: Text, }, Callout { callout: Callout, }, Quote { quote: TextAndChildren, }, BulletedListItem { bulleted_list_item: TextAndChildren, }, NumberedListItem { numbered_list_item: TextAndChildren, }, ToDo { to_do: ToDoFields, }, Toggle { toggle: TextAndChildren, }, Code { code: CodeFields, }, ChildPage { child_page: ChildPageFields, }, ChildDatabase { child_database: ChildDatabaseFields, }, Embed { embed: EmbedFields, }, Image { image: FileObject, }, Video { video: FileObject, }, File { file: FileObject, caption: Text, }, Pdf { pdf: FileObject, }, Bookmark { bookmark: BookmarkFields, }, Equation { equation: Equation, }, Divider, TableOfContents { table_of_contents: TableOfContents, }, Breadcrumb, ColumnList { column_list: ColumnListFields, }, Column { column: ColumnFields, }, LinkPreview { link_preview: LinkPreviewFields, }, Template { template: TemplateFields, }, LinkToPage { link_to_page: LinkToPageFields, }, Table { table: TableFields, }, SyncedBlock { synced_block: SyncedBlockFields, }, TableRow { table_row: TableRowFields, }, Unsupported, #[serde(other)] Unknown, }