GithubHelp home page GithubHelp logo

notion-dotnet / notion-sdk-net Goto Github PK

View Code? Open in Web Editor NEW
181.0 6.0 43.0 716 KB

A Notion SDK for .Net

License: MIT License

C# 99.72% Dockerfile 0.28%
notion sdk dotnet csharp api-client notion-dotnet notion-api api hacktoberfest hacktoberfest2022 hacktoberfest2023

notion-sdk-net's Introduction

Notion SDK for .Net

A simple and easy to use client for the Notion API


GitHub release (latest SemVer) GitHub

Build Status Build artifacts Publish Code CodeQL

LGTM Alerts LGTM Grade

GitHub last commit GitHub commit activity GitHub commit activity GitHub commit activity

GitHub repo size Lines of code

Provides the following packages:

Package Downloads Nuget
Notion.Net Nuget Nuget Nuget (with prereleases)

Installation

.Net CLI

dotnet add package Notion.Net

Note: default Notion-Version used by NuGet package versions

Package version Notion-Version
4.0.0-preview-1.8.21.2022 2022-06-28
3.0.0+ 2022-02-22
2.0.0+ 2021-08-16
1.0.0+ 2021-05-13

Usage

Before getting started, you need to create an integration and find the token. You can learn more about authorization here.

Import and initialize the client using the integration token created above.

var client = NotionClientFactory.Create(new ClientOptions
{
    AuthToken = "<Token>"
});

Make A request to any Endpoint. For example you can call below to fetch the paginated list of users.

var usersList = await client.Users.ListAsync();

Dependency Injection

Library also provides extension method to register NotionClient with Microsoft dependency injection.

services.AddNotionClient(options => {
  options.AuthToken = "<Token>";
});

Querying a database

After you initialized your client and got an id of a database, you can query it for any contained pages. You can add filters and sorts to your request. Here is a simple example:

// Date filter for page property called "When"
var dateFilter = new DateFilter("When", onOrAfter: DateTime.Now);

var queryParams = new DatabasesQueryParameters { Filter = dateFilter };
var pages = await client.Databases.QueryAsync(databaseId, queryParams);

Filters constructors contain all possible filter conditions, but you need to choose only condition per filter, all other should be null. So, for example this code would not filter by 2 conditions as one might expect:

var filter = new TextFilter("Name", startsWith: "Mr", contains: "John"); // WRONG FILTER USAGE

To use complex filters, use class CompoundFilter. It allows adding many filters and even nesting compound filters into each other (it works as filter group in Notion interface). Here is an example of filter that would return pages that were due in past month AND either had a certain assignee OR had high urgency:

var selectFilter = new SelectFilter("Urgency", equal: "High");
var assigneeFilter = new PeopleFilter("Assignee", contains: "some-uuid");
var dateFilter = new DateFilter("Due", pastMonth: new Dictionary<string, object>());

var orGroup = new List<Filter> { assigneeFilter, selectFilter };
var complexFiler = new CompoundFilter(
    and: new List<Filter> { dateFilter, new CompoundFilter(or: orGroup) }
);

Supported Endpoints

  • Databases
    • Query a database
    • Create a database
    • Update database
    • Retrieve a database
  • Pages
    • Retrieve a page
    • Create a page
    • Update page
    • Retrieve page property item
  • Blocks
    • Retrieve a block
    • Update a block
    • Retrieve block children
    • Append block children
    • Delete a block
  • Comments
    • Retrieve comments
    • Create comment
  • Users
    • Retrieve a User
    • List all users
    • Retrieve your token's bot user
  • Search

Enable internal logs

The library make use of ILoggerFactory interface exposed by Microsoft.Extensions.Logging. Which allow you to have ability to enable the internal logs when developing application to get additional information.

To enable logging you need to add the below code at startup of the application.

// pass the ILoggerFactory instance
NotionClientLogging.ConfigureLogger(logger);

You can set the LogLevel in config file.

{
  "Logging": {
    "LogLevel": {
      "Notion.Client": "Trace"
    }
  }
}

You can also refer examples/list-users example.

Contributors

This project exists thanks to all the people who contribute.

contributor image

Contribution Guideline

Hello! Thank you for choosing to help contribute to this open source library. There are many ways you can contribute and help is always welcome. You can read the detailed Contribution Guideline defined here - we will continue to improve it.

notion-sdk-net's People

Contributors

aleksei-oecd avatar ankursheel avatar asevos avatar dependabot[bot] avatar dmitry-vf avatar hermanschoenfeld avatar hognevevle avatar kashifsoofi avatar koditkarvedant avatar ksvaibhav avatar kurupapuru avatar kzhen avatar mikehutility avatar poltuu avatar randomuser14 avatar sotiriszogos avatar titaye avatar vijayvarmad avatar vinibeloni avatar winl-2022 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

notion-sdk-net's Issues

Update Readme

  • Add getting started instructions
  • Links to examples #10
  • Add contribution guidelines #63

Add Unit/Integration tests for endpoints

Endpoints

  • Databases
    • Retrieve
    • Query
    • List
  • Pages
    • Retrieve
    • Create
    • Update
  • Blocks
    • Retrieve Block Children
    • Append Block Children
  • Users
    • Retrieve a User
    • List all users
  • Search

Note: Fill free to create a PR for each endpoint this is just a placeholder issue to know the missing test cases for endpoints.

User mentions can only be of people

To be consistent with the Notion application, only users of type "people" can be mentioned in rich text objects or in people properties of databases. Trying to include users of type "bot" will return a validation error. Existing mentions of bot users is unaffected.

Notion API changelog reference: https://developers.notion.com/changelog/user-mentions-can-only-be-of-people

We may not need to add validation in the fetch database object but when we are going to add support for the create database then we may need to consider adding the validation on the models we use to create database. #56

Add support for Create new databases API

You can now use the Notion API to create a database as a subpage of an existing page.

Currently supported property types are title, rich_text, number, select. multi_select, date, people, files, checkbox, url, email, phone_number, created_time, created_by, last_edited_time, last_edited_by.

Notion API changelog: https://developers.notion.com/changelog/create-new-databases-with-post-databases

Example Request

curl --location --request POST 'https://api.notion.com/v1/databases/' \
--header 'Authorization: Bearer '"$NOTION_API_KEY"'' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: 2021-05-13' \
--data '{
    "parent": {
        "type": "page_id",
        "page_id": "98ad959b-2b6a-4774-80ee-00246fb0ea9b"
    },
    "title": [
        {
            "type": "text",
            "text": {
                "content": "Grocery List",
                "link": null
            }
        }
    ],
    "properties": {
        "Name": {
            "title": {}
        },
        "Description": {
            "rich_text": {}
        },
        "In stock": {
            "checkbox": {}
        },
        "Food group": {
            "select": {
                "options": [
                    {
                        "name": "🥦Vegetable",
                        "color": "green"
                    },
                    {
                        "name": "🍎Fruit",
                        "color": "red"
                    },
                    {
                        "name": "💪Protein",
                        "color": "yellow"
                    }
                ]
            }
        },
        "Price": {
            "number": {
                "format": "dollar"
            }
        },
        "Last ordered": {
            "date": {}
        },
        "Store availability": {
            "type": "multi_select",
            "multi_select": {
                "options": [
                    {
                        "name": "Duc Loi Market",
                        "color": "blue"
                    },
                    {
                        "name": "Rainbow Grocery",
                        "color": "gray"
                    },
                    {
                        "name": "Nijiya Market",
                        "color": "purple"
                    },
                    {
                        "name": "Gus'\''s Community Market",
                        "color": "yellow"
                    }
                ]
            }
        },
        "+1": {
            "people": {}
        },
        "Photo": {
            "files": {}
        }
    }
}'

Example Response

{
    "object": "database",
    "id": "bc1211ca-e3f1-4939-ae34-5260b16f627c",
    "created_time": "2021-07-08T23:50:00.000Z",
    "last_edited_time": "2021-07-08T23:50:00.000Z",
    "title": [
        {
            "type": "text",
            "text": {
                "content": "Grocery List",
                "link": null
            },
            "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
            },
            "plain_text": "Grocery List",
            "href": null
        }
    ],
    "properties": {
        "+1": {
            "id": "PNEQ",
            "type": "people",
            "people": {}
        },
        "In stock": {
            "id": "V>GQ",
            "type": "checkbox",
            "checkbox": {}
        },
        "Price": {
            "id": "V@]u",
            "type": "number",
            "number": {
                "format": "dollar"
            }
        },
        "Description": {
            "id": "V}lX",
            "type": "rich_text",
            "rich_text": {}
        },
        "Last ordered": {
            "id": "eVnV",
            "type": "date",
            "date": {}
        },
        "Store availability": {
            "id": "s}Kq",
            "type": "multi_select",
            "multi_select": {
                "options": [
                    {
                        "id": "cb79b393-d1c1-4528-b517-c450859de766",
                        "name": "Duc Loi Market",
                        "color": "blue"
                    },
                    {
                        "id": "58aae162-75d4-403b-a793-3bc7308e4cd2",
                        "name": "Rainbow Grocery",
                        "color": "gray"
                    },
                    {
                        "id": "22d0f199-babc-44ff-bd80-a9eae3e3fcbf",
                        "name": "Nijiya Market",
                        "color": "purple"
                    },
                    {
                        "id": "0d069987-ffb0-4347-bde2-8e4068003dbc",
                        "name": "Gus's Community Market",
                        "color": "yellow"
                    }
                ]
            }
        },
        "Photo": {
            "id": "yfiK",
            "type": "files",
            "files": {}
        },
        "Food group": {
            "id": "|JKd",
            "type": "select",
            "select": {
                "options": [
                    {
                        "id": "6d4523fa-88cb-4ffd-9364-1e39d0f4e566",
                        "name": "🥦Vegetable",
                        "color": "green"
                    },
                    {
                        "id": "268d7e75-de8f-4c4b-8b9d-de0f97021833",
                        "name": "🍎Fruit",
                        "color": "red"
                    },
                    {
                        "id": "1b234a00-dc97-489c-b987-829264cfdfef",
                        "name": "💪Protein",
                        "color": "yellow"
                    }
                ]
            }
        },
        "Name": {
            "id": "title",
            "type": "title",
            "title": {}
        }
    },
    "parent": {
        "type": "page_id",
        "page_id": "98ad959b-2b6a-4774-80ee-00246fb0ea9b"
    }
}

Page create test case missing Parent.

CreateAsync(newPage) in PageClientTests.cs should be getting an exception for you since it is missing Parent.

I based add page in my application on your test code and got exception. Works fine after adding Parent.

Your toolkit is exceptional. Thank you for creating it.

Add Continuous security analysis: LGTM

Add Continuous security analysis. https://lgtm.com/

A code analysis platform for finding zero-days and preventing critical vulnerabilities. Prevent bugs from ever making it to your project by using automated reviews that let you know when your code changes would introduce alerts into your project.

CI: Enforce a consistent coding style using CI Build

We already have defined the .editorcofig file to maintain consistent coding style. We can format the code using the dotnet format tool locally but it is very easy to miss.

To make sure every code committed in the repo follow the consistent code style we should add a step in CI build pipeline to validate the code style.

Add usage examples

Add examples solution to use the library in the below types of projects

  • Asp.Net Core
  • Console Application

Retrieve and update blocks with GET and PATCH /v1/blocks/:id

You can now retrieve and update block objects with the Notion API! The PATCH endpoint currently supports updating paragraph, heading_1, heading_2, heading_3, bulleted_list_item, numbered_list_item, toggle and to_do blocks.

Retrieve a Block

The Retrieve a Block endpoint returns a Block Object.

Example GET Request

curl 'https://api.notion.com/v1/blocks/9bc30ad4-9373-46a5-84ab-0a7845ee52e6' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2021-05-13'

Example GET Response

{
  "object": "block",
  "id": "9bc30ad4-9373-46a5-84ab-0a7845ee52e6",
  "created_time": "2021-03-16T16:31:00.000Z",
  "last_edited_time": "2021-03-16T16:32:00.000Z",
  "has_children": false,
  "type": "to_do",
  "to_do": {
    "text": [
      {
        "type": "text",
        "text": {
          "content": "Lacinato kale",
          "link": null
        },
        "annotations": {
          "bold": false,
          "italic": false,
          "strikethrough": false,
          "underline": false,
          "code": false,
          "color": "default"
        },
        "plain_text": "Lacinato kale",
        "href": null
      }
    ],
    "checked": false
  }
}

Update a Block

The new PATCH /v1/blocks/:id endpoint supports updating block content (the properties within the block type object) and returns the updated Block Object, same as the GET endpoint shown above. See the Update a Block documentation for more detail.

Example PATCH Request

curl https://api.notion.com/v1/blocks/9bc30ad4-9373-46a5-84ab-0a7845ee52e6 \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2021-05-13" \
  -X PATCH \
  --data '{
  "to_do": {
    "text": [{ 
      "text": { "content": "Lacinato kale" } 
      }],
    "checked": false
  }
}'

Notion API reference ref: https://developers.notion.com/changelog/retrieve-and-update-blocks-with-get-and-patch-v1blocksid

Add Readme for Nuget package

Recently NuGet provides ability to pack Readme.md file with your package. This is still in preview but when you actually visit the NuGet.org they already starting showing the readme file. This will help users to get started easily instead of them visiting the GitHub to read the readme files.

Number property type in Database now support more currency formats

There is recent update from Notion API. The number property type in databases now supports additional currency options.

The new options are:

  • "hong_kong_dollar"
  • "new_zealand_dollar"
  • "krona"
  • "norwegian_krone"
  • "mexican_peso"
  • "rand"
  • "new_taiwan_dollar"
  • "danish_krone"
  • "zloty"
  • "baht"
  • "forint"
  • "koruna"
  • "shekel"
  • "chilean_peso"
  • "philippine_peso"
  • "dirham"
  • "colombian_peso"
  • "riyal"
  • "ringgit"
  • "leu"

This impacts the number configuration of databases.

Notion API change log: https://developers.notion.com/changelog/number-properties-now-support-more-currency-formats

Page objects now contain url

Page objects now return the web address of the page in the url key.

Note: This impacts endpoints that return page object:

  • pages endpoints
  • query database endpoint.

Example JSON Response

{
  "object": "page",
  "id": "251d2b5f-268c-4de2-afe9-c71ff92ca95c",
    "created_time": "2020-03-17T19:10:04.968Z",
    "last_edited_time": "2020-03-17T21:49:37.913Z",
  "parent": {
    "type": "database_id",
    "database_id": "48f8fee9-cd79-4180-bc2f-ec0398253067"
  },
  "archived": false,
  "url": "https://www.notion.so/Avocado-251d2b5f268c4de2afe9c71ff92ca95c",
  "properties": {
    "Name": {
      "id": "title",
      "type": "title",
      "title": [
        {
          "type": "text",
          "text": {
            "content": "Avocado",
            "link": null
          },
          "annotations": {
            "bold": false,
            "italic": false,
            "strikethrough": false,
            "underline": false,
            "code": false,
            "color": "default"
          },
          "plain_text": "Avocado",
          "href": null
        }
      ]
    }
  }
}

Add missing enums for rollups

As per, the following screenshot, show_unique and show_original are missing from the rollup enum values

image

There is also another bug where the boolean value for a formula can be null but the deserializer does not account for it.

Filters should not be serialized with default values, SinglePropertyFilter has wrong format

I tripped over this bug trying to make a simple bot fetching tasks from my Notion.
Here is the code I executed. I suspected I used filters wrong, but I couldn't find any other other way to do it.

var client = new NotionClient(new ClientOptions
{
    AuthToken = "MY_TOKEN"
});

var dateFilter = new DateFilter
{
    Property = "When",
    OnOrAfter = DateTime.Now,
};
var queryParams = new DatabasesQueryParameters
{
    Filter = dateFilter,
};
var databaseId = "MY_DB_ID";

var results = await client.Databases.QueryAsync(databaseId, queryParams);

So the expected behavior was to get in results all my pages with property "When" being set to some date in the future. However, it fetched me all pages in my Notion database.
I played around with it a bit to find out what is going on and found out that in RestClinent.PostAsync() serialized filter looked like this:

{"Filter":{"equals":"0001-01-01T00:00:00","before":"0001-01-01T00:00:00","after":"0001-01-01T00:00:00","on_or_before":"0001-01-01T00:00:00","on_or_after":"2021-05-28T18:29:03.0391769+03:00","is_empty":true,"is_not_empty":true,"Property":"When"}}

It added to filter all possible filter states, that were not null. This were all bools and DateTime properties.

I updated DateFilter so it would serialize only properties added to it manually:

public class DateFilter : SinglePropertyFilter
{
    [JsonProperty("equals")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public Nullable<DateTime> Equal { get; set; }

    [JsonProperty("before")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public Nullable<DateTime> Before { get; set; }

    [JsonProperty("after")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public Nullable<DateTime> After { get; set; }

    [JsonProperty("on_or_before")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public Nullable<DateTime> OnOrBefore { get; set; }

    [JsonProperty("on_or_after")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public Nullable<DateTime> OnOrAfter { get; set; }

    [JsonProperty("past_week")]
    public Dictionary<string, object> PastWeek { get; set; }

    [JsonProperty("past_month")]
    public Dictionary<string, object> PastMonth { get; set; }

    [JsonProperty("past_year")]
    public Dictionary<string, object> PastYear { get; set; }

    [JsonProperty("next_week")]
    public Dictionary<string, object> NextWeek { get; set; }

    [JsonProperty("next_month")]
    public Dictionary<string, object> NextMonth { get; set; }

    [JsonProperty("next_year")]
    public Dictionary<string, object> NextYear { get; set; }

    [JsonProperty("is_empty")]
    public Nullable<bool> IsEmpty { get; set; }

    [JsonProperty("is_not_empty")]
    public Nullable<bool> IsNotEmpty { get; set; }
}

Then it was serializing correctly, however I ran into another issue: filters have wrong format, not supported by Notion API (https://developers.notion.com/reference/post-database-query#post-database-query-filter). I received filter of the following format:

{
    "Filter": {
        "Property": "When",
        "on_or_after": "2021-05-28T18:35:56.0871291+03:00",
    }
}

While correct single property filter format according to docs would be:

{
    "filter": {
        "property": "When",
        "date": {
            "on_or_after": "2021-05-28T18:35:56.0871291+03:00"
        }
    }
}

@KoditkarVedant I could fix this issues and add a user friendly filter constructor, if you would accept my contributions.

Update existing databases with PATCH /v1/databases

You can now use the Notion API to update databases!

Supported updates are:

  • renaming the database
  • adding and removing properties
  • renaming properties
  • updating property types.

Note that updating the name and color select and multi select options is not supported.

Example request

curl --location --request PATCH 'https://api.notion.com/v1/databases/668d797c-76fa-4934-9b05-ad288df2d136' \
--header 'Authorization: Bearer '"$NOTION_API_KEY"'' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: 2021-07-27' \
--data '{
    "title": [
        {
            "text": {
                "content": "Today'\''s grocery list"
            }
        }
    ],
    "properties": {
        "+1": null,
        "Photo": {
            "url": {}
        },
        "Store availability": {
            "multi_select": {
                "options": [
                    {
                        "name": "Duc Loi Market"
                    },
                    {
                        "name": "Rainbow Grocery"
                    },
                    {
                        "name": "Gus'\''s Community Market"
                    },
                    {
                        "name": "The Good Life Grocery",
                        "color": "orange"
                    }
                ]
            }
        }
    }       
}'

Example response

{
  "object": "database",
  "id": "668d797c-76fa-4934-9b05-ad288df2d136",
  "created_time": "2020-03-17T19:10:00.000Z",
  "last_edited_time": "2021-08-11T17:26:00.000Z",
  "parent": {
    "type": "page_id",
    "page_id": "48f8fee9-cd79-4180-bc2f-ec0398253067"
  },
  "title": [
    {
      "type": "text",
      "text": {
        "content": "Today'\''s grocery list",
        "link": null
      },
      "annotations": {
        "bold": false,
        "italic": false,
        "strikethrough": false,
        "underline": false,
        "code": false,
        "color": "default"
      },
      "plain_text": "Today'\''s grocery list",
      "href": null
    }
  ],
  "properties": {
    "Name": {
      "id": "title",
      "type": "title",
      "title": {}
    },
    "Description": {
      "id": "J@cS",
      "type": "rich_text",
      "rich_text": {}
    },
    "In stock": {
      "id": "{xY`",
      "type": "checkbox",
      "checkbox": {}
    },
    "Food group": {
      "id": "TJmr",
      "type": "select",
      "select": {
        "options": [
          {
            "id": "96eb622f-4b88-4283-919d-ece2fbed3841",
            "name": "🥦Vegetable",
            "color": "green"
          },
          {
            "id": "bb443819-81dc-46fb-882d-ebee6e22c432",
            "name": "🍎Fruit",
            "color": "red"
          },
          {
            "id": "7da9d1b9-8685-472e-9da3-3af57bdb221e",
            "name": "💪Protein",
            "color": "yellow"
          }
        ]
      }
    },
    "Price": {
      "id": "cU^N",
      "type": "number",
      "number": {
        "format": "dollar"
      }
    },
    "Cost of next trip": {
      "id": "p:sC",
      "type": "formula",
      "formula": {
        "value": "if(prop(\"In stock\"), 0, prop(\"Price\"))"
      }
    },
    "Last ordered": {
      "id": "]\\R[",
      "type": "date",
      "date": {}
    },
    "Meals": {
      "type": "relation",
      "relation": {
        "database": "668d797c-76fa-4934-9b05-ad288df2d136",
        "synced_property_name": null
      }
    },
    "Number of meals": {
      "id": "Z\\Eh",
      "type": "rollup",
      "rollup": {
        "rollup_property_name": "Name",
        "relation_property_name": "Meals",
        "rollup_property_id": "title",
        "relation_property_id": "mxp^",
        "function": "count"
      }
    },
    "Store availability": {
      "type": "multi_select",
      "multi_select": {
        "options": [
          [
            {
              "id": "d209b920-212c-4040-9d4a-bdf349dd8b2a",
              "name": "Duc Loi Market",
              "color": "blue"
            },
            {
              "id": "70104074-0f91-467b-9787-00d59e6e1e41",
              "name": "Rainbow Grocery",
              "color": "gray"
            },
            {
              "id": "6c3867c5-d542-4f84-b6e9-a420c43094e7",
              "name": "Gus's Community Market",
              "color": "yellow"
            },
            {
                            "id": "a62fbb5f-fed4-44a4-8cac-cba5f518c1a1",
              "name": "Good life grocery",
              "color": "orange"
           }
          ]
        ]
      }
    }
    "Photo": {
      "id": "aTIT",
      "type": "url",
      "url": {}
    }
  }
}

Notion API changelog ref: https://developers.notion.com/changelog/update-existing-databases-with-patch-v1databases

DateProperty has type MultiSelect

DateProperty.cs

public class DateProperty : Property
{
public override PropertyType Type => PropertyType.MultiSelect;
public Dictionary<string, object> Date { get; set; }
}

Unable to append child blocks

Looks like IObject.Object (ObjectType enum) writes as number

Exception:

NotionApiException

Exception message:

body failed validation: body.children[0].object should be "block", instead was 2.

Stack Trace:

at Notion.Client.RestClient.SendAsync(String requestUri, HttpMethod httpMethod, IDictionary`2 queryParams, IDictionary`2 headers, Action`1 attachContent, CancellationToken cancellationToken) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\RestClient\RestClient.cs:line 102
   at Notion.Client.RestClient.PatchAsync[T](String uri, Object body, IDictionary`2 queryParams, IDictionary`2 headers, JsonSerializerSettings serializerSettings, CancellationToken cancellationToken) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\RestClient\RestClient.cs:line 142
   at Notion.Client.BlocksClient.AppendChildrenAsync(String blockId, BlocksAppendChildrenParameters parameters) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\Api\Blocks\BlocksClient.cs:line 48
   at CompanyName.ProjectStructureAutomatization.App.AppendPageRelationsRecursive(String parentId, Page page) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\CompanyName.TasksStructureAutomatization\App.cs:line 120

Serialization Stack Trace:

   at Notion.Client.RestClient.SendAsync(String requestUri, HttpMethod httpMethod, IDictionary`2 queryParams, IDictionary`2 headers, Action`1 attachContent, CancellationToken cancellationToken) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\RestClient\RestClient.cs:line 102
   at Notion.Client.RestClient.PatchAsync[T](String uri, Object body, IDictionary`2 queryParams, IDictionary`2 headers, JsonSerializerSettings serializerSettings, CancellationToken cancellationToken) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\RestClient\RestClient.cs:line 142
   at Notion.Client.BlocksClient.AppendChildrenAsync(String blockId, BlocksAppendChildrenParameters parameters) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\NotionDotNet.NotionSdkNet\Src\Notion.Client\Api\Blocks\BlocksClient.cs:line 48
   at CompanyName.ProjectStructureAutomatization.App.AppendPageRelationsRecursive(String parentId, Page page) in F:\AllProjects\CompanyName\ToolsAndAutomatization\TasksStructureAutomatization\CompanyName.TasksStructureAutomatization\App.cs:line 120

Proposal: filter constructors for cleaner initialization

So currently creating just one filter takes 8 lines of code. It is not that much, but making a compound filter with both "and" and "or" condtions takes up to 40 lines, which I would like to optimize.
Currently initialization of a filter class looks like this:

var filter = new PeopleFilter
{
    Property = "Assignee",
    People = new PeopleFilter.Condition
    {
        IsNotEmpty = true
    }
};

And I would like it to look something like this:

var filter = new PeopleFilter("Assignee", PeopleFilter.ConditionType.IsNotEmpty, true);

For this I can add ConditionType enums to filter classes and choose which property to assign in [Filter].Condition initialization automatically. So I expect it to look something like this:

public class PeopleFilter : SinglePropertyFilter
{
    public Condition People { get; set; }

    public PeopleFilter(string property, PeopleFilter.ConditionType conditionType, object value)
    {
        var condition = new Condition();
        switch (conditionType)
        {
            case ConditionType.Contains:
                condition.Contains = (string)value;
                break;
            case ConditionType.DoesNotContain:
                condition.DoesNotContain = (string)value;
                break;
            case ConditionType.IsEmpty:
                condition.IsEmpty = (bool)value;
                break;
            case ConditionType.IsNotEmpty:
                condition.IsEmpty = (bool)value;
                break;
            default:
                break;
        }

        Property = property;
        People = condition;
    }

    public class Condition
    {
      // ...
    }

    public enum ConditionType
    {
        Contains,
        DoesNotContain,
        IsEmpty,
        IsNotEmpty,
    }
}

Of course there are possible issues with typing value wrongfully. I also thought about making constructors overloads for each possible value type, but that would require creating separate enums for each type.

Please, let me know your thoughts on this idea.

'errorResponse' is null on at least one execution path.

Code in RestClient.BuildException method try to access the errorResponse.Message where errorResponse could be null and may throw exception.

private static async Task<Exception> BuildException(HttpResponseMessage response)
{
    var errorBody = await response.Content.ReadAsStringAsync();

    NotionApiErrorResponse errorResponse = null;
    if (!string.IsNullOrWhiteSpace(errorBody))
    {
        try
        {
            errorResponse = JsonConvert.DeserializeObject<NotionApiErrorResponse>(errorBody);
        }
        catch
        {
        }
     }

     return new NotionApiException(response.StatusCode, errorResponse?.ErrorCode, errorResponse.Message);
}

It should be changed to errorResponse?.Message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.