Giter VIP home page Giter VIP logo

go-notion's Introduction

I’m David Stotijn, a software engineer from Amsterdam.

Senior Software Engineer with 10 years’ experience building distributed services.

✅ Go ✅ JavaScript/TypeScript (Node.js and client) ✅ Cloud Infrastructure (AWS, Google Cloud, Docker) ✅ APIs (REST, GraphQL, gRPC) ✅ Web frameworks/libraries (React, Next.js, NestJS) ✅ Test Driven Development ✅ Observability Engineering (Prometheus, Grafana, OpenCensus)

  • 10 years’ experience building web applications and services at agencies and start/scale-ups.
  • 6 years’ experience building and maintaining Go projects, mainly distributed web services.
  • 5 years’ experience with JavaScript/TypeScript in Node.js and React projects.
  • Built APIs (RESTful, GraphQL, gRPC), (queue) workers, third-party API integrations.
  • Used various (managed) AWS and Google Cloud products for: databases (PostgreSQL, Cloud Spanner, DynamoDB, MongoDB), message brokers, object storage and caching.
  • I’m comfortable with immersing myself in a (new) business domain and pragmatically designing and building software in it.
  • Empathetic, with a humble mindset. I can quickly get up to speed in a new work environment and communicate effectively with team members and stakeholders.

go-notion's People

Contributors

asfal avatar bassettb avatar biblion84 avatar dstotijn avatar mmmommm avatar nozo-moto avatar saltbo avatar sivchari 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  avatar  avatar  avatar

go-notion's Issues

Could not get Block children ID in function FindBlockChildrenByID

When I call the api https://api.notion.com/v1/blocks/{block_id}/children, it return the block in clude the block id.
In my case, the block contain the table, so I need the id to query formation in the table.
But when I use the funtion FindBlockChildrenByID it only return the title of the table and the id is the private variable, so I can not read it.

There is any solution for me to get the id of children block of a page. Or I should call API instead of using this library for my problem.

Excessive entry of People User Type in DatabasePageProperty struct issue

In the CreatePage function, when data is entered in the People type of the Type database, due to excessive DatabasePageProperty->People User struct item
body.properties.People.people[0].type should be not present, instead was "".
body.properties.People.people[0].name should be not present, instead was "".
body.properties.People.people[0].avatar_url should be not present, instead was "".
body.properties.People.people[0].person should be not present or an object, instead was null.
body.properties.People.people[0].bot should be not present or an object, instead was null. (code: validation_error, status: 400)
error occurs.
However, It can be solved by adding omitempty to each json item of User struct.

Update database entry Title

Hello, I'm trying to update a database entry title field (Name in my case) but I don't manage to do so. If I use Name on the properties it told me to use the Title, and using the Title does nothing (no errors). I can update other properties without issue.

sample code:

name := "New name"

page, err := client.UpdatePage(ctx, "<pageid>", notion.UpdatePageParams{
	Title: []notion.RichText{
		{
			PlainText: name,
			Text: &notion.Text{
				Content: product.Name,
			},
		},
	},
)

I've tried several combinations, but nothing seems to being able to update the page title. I tried using "Title" as the field name (in case it was some JSON hardcoding) but that didn't work either.

Thanks for your work on this!

Encountering Error Code 500 on Database Query

When the following line executes, it returns back stating an error with code 500 occurs.

response, err := client.QueryDatabase(context.Background(), id, query)

I'm not particularly sure where the issue is arising, so any help resolving is appreciated!

Retrieve File

Notion added the file url and an expiry time to the files object:
https://developers.notion.com/reference/file-object

Are you planning to add this in the future?

For the beginning, in my opinion, it would be enough to add the two fields to the File struct and maybe add later the functionality of actually downloading the file.

Consider typing interface{} fields?

First of all, thanks for the work you're putting into this!

There are couple of places in the Go API where the type of a field is only known at runtime (eg. Page.Properties), so the field is typed as interface{} in Go. One approach that's used eg. by the protobuf runtime is to use an interface with a "dummy" method that uniquely identifies the implementors, which helps both IDEs/language servers to do autocompletion and the compiler to ensure that the code is correct.

A simple example

type Page struct {
   Properties IsPageProperties
}

type IsPageProperties interface { isPageProperties() }

type PageProperties struct { /* ... */ }

func (PageProperties) isPageProperties() {}

type DatabasePageProperties struct {  /* ... */  }

func (DatabasePageProperties) isPageProperties() {}

let me know if you think this approach makes sense, and I can try to send a PR.

Tests

Congrats on this project; you did an amazing thing. I'd love to make some contributions, but I wanted to see which tests need to be implemented? To send some PRs for.

Color assigning for DB SelectOptions

I thoroughly enjoy using your client, it makes a lot of sense when you get the hang of it.
Unfortunately, I have been struggling with something that doesn't seem to stem from my code (feel free to contradict using the code provided below). When creating a new Page in a Database, I add a few Select properties with SelectOptions while filling the Color and Name fields.
The API doesn't seem to receive the Color information though and the Options appear a different color every time in the Notion interface. This leads to the inability to add any more Pages due to the inconsistent colors.

I scoured the Notion API Interface and the docs of this API but I didn't seem to find any note about this.

In this specific example, City, Locality, Category, Opening Days, and Train Station are always random colors and I cannot seem to be able to set them.

package main

import (
	"context"
	"fmt"
	"html"

	"github.com/dstotijn/go-notion"
)

func CreateMuseumPage(mus Museum, db_id string, client notion.Client) (notion.Page, error) {
	specifics, err := ParseSpecifics(mus)
	city := ParseCity(mus.AddressLocality)
	categ := ParseCategory(mus.Themes)
	if err != nil {
		return notion.Page{}, err
	}
	params := notion.CreatePageParams{
		ParentType: "database_id",
		ParentID:   db_id,
		DatabasePageProperties: &notion.DatabasePageProperties{
			"Name": notion.DatabasePageProperty{
				Title: IntoRichTextArray(mus.Name),
			},
			"Description": notion.DatabasePageProperty{
				RichText: IntoRichTextArray(mus.ShortDescription),
			},
			"URL": notion.DatabasePageProperty{
				URL: &mus.DetailURL,
			},
			"Locality": notion.DatabasePageProperty{
				Select: &notion.SelectOptions{
					Name:  mus.AddressLocality,
					Color: city.Color(),
				},
			},
			"Category": notion.DatabasePageProperty{
				Select: &notion.SelectOptions{
					Name:  categ.String(),
					Color: notion.ColorOrange,
				},
			},
			"City": notion.DatabasePageProperty{
				Select: &notion.SelectOptions{
					Name:  city.String(),
					Color: city.Color(),
				},
			},
			"Closed": notion.DatabasePageProperty{
				Checkbox: &mus.TemporaryClosed,
			},
			"Openings": notion.DatabasePageProperty{
				RichText: IntoRichTextArray(specifics.opening),
			},
			"Phone": notion.DatabasePageProperty{
				PhoneNumber: &specifics.phone,
			},
			"Email": notion.DatabasePageProperty{
				Type:  notion.DBPropTypeEmail,
				Email: &specifics.email,
			},
			"Website": notion.DatabasePageProperty{
				Type: notion.DBPropTypeURL,
				URL:  &specifics.website,
			},
			"Train Station": notion.DatabasePageProperty{
				Select: &notion.SelectOptions{
					Name:  specifics.station,
					Color: city.Color(),
				},
			},
			"Opening Hours": notion.DatabasePageProperty{
				RichText: IntoRichTextArray(specifics.openingHours),
			},
			"Opening Days": notion.DatabasePageProperty{
				MultiSelect: CreateDayOptions(specifics.openingDays),
			},
		},
		Icon: &notion.Icon{
			Type:  notion.IconTypeEmoji,
			Emoji: categ.Emoji(),
		},
		Cover: &notion.Cover{
			Type: notion.FileTypeExternal,
			External: &notion.FileExternal{
				URL: mus.CoverPhoto.ResizableURL + "?max-h=600&max-w=1500",
			},
		},
	}
	fmt.Print("[NOTION] Creating page \"" + mus.Name + "\" in the Musea database...")
	page, err := client.CreatePage(context.Background(), params)
	if err != nil {
		return notion.Page{}, err
	}
	fmt.Println("Done")
	return page, nil
}

func CreateDayOptions(days []Day) []notion.SelectOptions {
	var select_options []notion.SelectOptions
	for _, day := range DaysToString(days) {
		select_options = append(select_options, notion.SelectOptions{
			Name:  day,
			Color: notion.ColorPurple,
		})
	}
	return select_options
}

func DaysToString(vs []Day) []string {
	vsm := make([]string, len(vs))
	for i, v := range vs {
		vsm[i] = v.LongString()
	}
	return vsm
}

func IntoRichText(base string) notion.RichText {
	t := &notion.Text{
		Content: html.UnescapeString(base),
	}
	rt := notion.RichText{
		Text: t,
	}
	return rt
}

func IntoRichTextArray(base string) []notion.RichText {
	return []notion.RichText{IntoRichText(base)}
}
type City int64

const (
	Brussels City = iota
	Gent
	Mechelen
	Antwerp
	NotImpl
)

func (me City) String() string {
	return []string{"Brussels", "Gent", "Mechelen", "Antwerp", ""}[me]
}

func (me City) Color() notion.Color {
	return []notion.Color{notion.ColorBlue, notion.ColorPurple, notion.ColorBrown, notion.ColorOrange}[me]
}

The resulting error doesn't really matter but I'll stick it in here in case you can learn more from it than I can :^)

[NOTION] Creating page "Musée Mode &amp; Dentelle" in the Musea database...Done
[NOTION] Creating page "Musée de la Banque nationale de Belgique" in the Musea database...notion: failed to create page: Select option color doesn't match existing for 68ad963d-18a2-49b4-a6a9-96fe36552c33. Select option color doesn't match existing for b1f3eb78-f05c-493d-8843-2735ddd4300a. Select option color doesn't match existing for 385e8aaa-a523-4e99-9da9-7d2031ba6ab2. Select option color doesn't match existing for e6154c30-e6ac-4436-beb8-aa3c9acd0184. (code: validation_error, status: 400)

If you have any quick fixes for this, it would be absolutely amazing. Thank you in advance

User object not being marshalled properly when trying to update a user in the People type DatabasePageProperty

Hi, great client!

When trying to update a People column in a database page (row), it seems that the User object is not being marshalled to the proper JSON object per the api.

Example usage of updating a page:

user := notion.User{BaseUser:  notion.BaseUser{ID: "<user-id>"}}
newPageProperties := notion.DatabasePageProperties{}
newPageProperties["Contributors"] = notion.DatabasePageProperty{People: []notion.User{user}}
res, err := n.Client.UpdatePage(ctx, "<page-id>", notion.UpdatePageParams{
		DatabasePageProperties: *newPageProperties,
})
if err != nil {
    fmt.Println(err)
}

The output error shows:

notion: failed to update page properties: body failed validation. Fix one:
body.properties.Contributors.people[0].type should be not present, instead was `""`.
body.properties.Contributors.people[0].name should be not present, instead was `""`.
body.properties.Contributors.people[0].avatar_url should be not present, instead was `""`.
body.properties.Contributors.people[0].person should be not present or an object, instead was `null`.
body.properties.Contributors.people[0].bot should be not present or an object, instead was `null`. (code: validation_error, status: 400)

from looking at the source code, I suspect the problem might be that the struct don't have an omitempty tag on their respective JSON representation. I'm happy to contribute an MR if needed

Non-consistent use of objects/pointers

In the whole package, it is not clear when pointers are used. There can be two string-type fields in one structure. One of them will be a pointer, and the second is not.
Example:

go-notion/rich_text.go

Lines 3 to 12 in c675641

type RichText struct {
Type RichTextType `json:"type,omitempty"`
Annotations *Annotations `json:"annotations,omitempty"`
PlainText string `json:"plain_text,omitempty"`
HRef *string `json:"href,omitempty"`
Text *Text `json:"text,omitempty"`
Mention *Mention `json:"mention,omitempty"`
Equation *Equation `json:"equation,omitempty"`
}

Or a more illustrative example:

go-notion/page.go

Lines 44 to 67 in c675641

type DatabasePageProperty struct {
ID string `json:"id,omitempty"`
Type DatabasePropertyType `json:"type,omitempty"`
Title []RichText `json:"title,omitempty"`
RichText []RichText `json:"rich_text,omitempty"`
Number *float64 `json:"number,omitempty"`
Select *SelectOptions `json:"select,omitempty"`
MultiSelect []SelectOptions `json:"multi_select,omitempty"`
Date *Date `json:"date,omitempty"`
Formula *FormulaResult `json:"formula,omitempty"`
Relation []Relation `json:"relation,omitempty"`
Rollup *RollupResult `json:"rollup,omitempty"`
People []User `json:"people,omitempty"`
Files []File `json:"files,omitempty"`
Checkbox *bool `json:"checkbox,omitempty"`
URL *string `json:"url,omitempty"`
Email *string `json:"email,omitempty"`
PhoneNumber *string `json:"phone_number,omitempty"`
CreatedTime *time.Time `json:"created_time,omitempty"`
CreatedBy *User `json:"created_by,omitempty"`
LastEditedTime *time.Time `json:"last_edited_time,omitempty"`
LastEditedBy *User `json:"last_edited_by,omitempty"`
}

Why is a Date field a pointer to a Date type, and a RichText a list of structures, not a list of pointers to them?

P.S. I'm not the most experienced go developer in the world 😀, so I may not understand a lot.

"Failed to parse HTTP response" on database query

I'm trying to make a simple query for a selection from the database.

client := notion.NewClient("secret_0aXXXXXXXXXXX")

res, err := client.QueryDatabase(context.TODO(), "aaaaa-bbbbb-4fc8-b220-xxxxx", &notion.DatabaseQuery{
	Filter: notion.DatabaseQueryFilter{
		Property: "Паркран",
		Text: &notion.TextDatabaseQueryFilter{
			Contains: "parkrun",
		},
	},
})

Unfortunately I get an error:

notion: failed to parse HTTP response: json: cannot unmarshal number into Go struct field DatabaseQueryResponse.results of type notion.NumberMetadata

After tweaking your code a little, I printed out the document that the library receives from the server. There is nothing private in this database, so I bring the document in full:

response.json
{
  "object": "list",
  "results": [
    {
      "object": "page",
      "id": "d2edfb6c-2aa2-4f7a-91f2-xxxxxxx",
      "created_time": "2021-05-24T10:45:05.833Z",
      "last_edited_time": "2021-05-24T10:45:05.833Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-xxxxxxxxx" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 25 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "30:20", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "30:20",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-04-24", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "44.01%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "44.01%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 32 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "a8d67af1-0707-4890-9c94-8efa1097b546",
      "created_time": "2021-05-24T10:45:04.432Z",
      "last_edited_time": "2021-05-24T10:45:04.432Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 54 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "30:49", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "30:49",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-05-22", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "43.32%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "43.32%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 74 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "a79f7eba-97df-49f9-8fe5-fd5b60e1a986",
      "created_time": "2021-05-24T10:45:04.420Z",
      "last_edited_time": "2021-05-24T10:45:04.420Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 42 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "30:27", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "30:27",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-05-08", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "43.84%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "43.84%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 60 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "e32c597e-5959-4d14-8d73-a45762bc0fa0",
      "created_time": "2021-05-24T10:45:04.403Z",
      "last_edited_time": "2021-05-24T10:45:04.403Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 46 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "30:03", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "30:03",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-05-01", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "44.43%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "44.43%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 58 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "ac686d42-05bf-4c4d-b1fc-ae7ce0992d79",
      "created_time": "2021-05-24T10:45:04.388Z",
      "last_edited_time": "2021-05-24T10:45:04.388Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 54 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "31:43", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "31:43",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-04-17", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "41.83%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "41.83%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 73 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "df95b4d1-2a51-4ace-8fcb-a886aa2afb74",
      "created_time": "2021-05-24T10:45:04.373Z",
      "last_edited_time": "2021-05-24T10:45:04.373Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 70 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "32:15", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "32:15",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-04-03", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "41.14%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "41.14%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 99 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    },
    {
      "object": "page",
      "id": "b3cb19fc-1e72-4ac5-a74f-197cbc150fa7",
      "created_time": "2021-05-24T10:45:04.362Z",
      "last_edited_time": "2021-05-24T10:45:04.362Z",
      "parent": { "type": "database_id", "database_id": "738ab074-8597-4fc8-b220-813c3dc75528" },
      "archived": false,
      "properties": {
        "Место среди М/Ж": { "id": "InK~", "type": "number", "number": 59 },
        "Время": {
          "id": "U^E~",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "30:29", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "30:29",
              "href": null
            }
          ]
        },
        "Дата": { "id": "b@g=", "type": "date", "date": { "start": "2021-04-10", "end": null } },
        "Рейтинг": {
          "id": "sJqx",
          "type": "rich_text",
          "rich_text": [
            {
              "type": "text",
              "text": { "content": "43.52%", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "43.52%",
              "href": null
            }
          ]
        },
        "Место в общем зачёте": { "id": "~dWC", "type": "number", "number": 81 },
        "Паркран": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "parkrun Natashinsky", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "parkrun Natashinsky",
              "href": null
            }
          ]
        }
      }
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Parsing time error in `FindBlockChildrenByID` function

Thank you for making golang sdk for notion api.

I get an error when I run this code.

func main() {
  a, err := notion.NewClient(MY_TOKEN).FindBlockChildrenByID(context.Background(), TEST_PAGE_ID)
  if err != nil {
    log.Println(err)
  }
  fmt.Println(a)
}
2021/05/23 15:24:30 notion: failed to parse HTTP response: parsing time ""2021-12-25"" as ""2006-01-02T15:04:05Z07:00"": cannot parse """ as "T"
{[] false <nil>}

my go.mod file

module main

go 1.14

require (
        github.com/dstotijn/go-notion v0.1.5
)

Impossible to create an empty DatabaseQueryFilter to fetch all rows from a database

Description

Impossible to create a DatabaseQuery with an empty DatabseQueryFilter. Fields that do not have empty values (such as embedded structs) cannot be omitted. Source

To Reproduce

Populate your environment variables with valid values for NOTION_SECRET_API_KEY and NOTION_DATABASE_ID and run the following code.

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/dstotijn/go-notion"
)

func main() {
	client := notion.NewClient(os.Getenv("NOTION_SECRET_API_KEY"))
	rows, err := client.QueryDatabase(context.Background(), os.Getenv("NOTION_DATABASE_ID"), &notion.DatabaseQuery{
		PageSize: 10,
	})
	fmt.Println("======= ERROR ======")
	fmt.Println(err)
	fmt.Println("======= ROWS ======")
	fmt.Println(rows)
}

Given the following table
Screen Shot 2021-05-24 at 10 10 24 PM
I go the following error
Screen Shot 2021-05-24 at 10 11 24 PM

Saving empty values

Hey,

it seems impossible to save or update pages in a database with empty values ("", nil, [], ...). Since empty values are omitted in json encoding, notion responds with "body.properties.. should be defined, instead was undefined".

Is there a way to store empty values, that I am not aware of? Otherwise, this seems to be a bug or explicitly not supported.

Thanks

`CreatePage` function always return 400 error

First of all ,thanks for creating the notino-sdk for go.

when the following code execute always return 400 error.

go version go1.15.6 darwin/amd64

func getClient(apiKey string) *notion.Client {
	return notion.NewClient(apiKey)
}

func createPage(c echo.Context) error {
	notionApi := os.Getenv("NOTION_API")
	client    := getClient(notionApi)
	ctx       := context.Background()
	parentId  := "{page_id}"

	titleText := &notion.Text{
		Content: "this is a title of the created page",
	}
	title := []notion.RichText{
		{
			Type: notion.RichTextTypeText,
			Text: titleText,
		},
	}
	params := notion.CreatePageParams{
		ParentType: notion.ParentTypePage,
		ParentID:   parentId,
		Title:      title,
	}

	page, err := client.CreatePage(ctx, params)
	if err != nil {
		fmt.Printf("%s",err)
	}
        fmt.Println(page)
	return nil
}

The following error code will be returned when createPage function is executed.

notion: failed to create page: body failed validation. Fix one: body.parent.type should be not present, instead was `"database_id"`. body.parent.page_id should be defined, instead was `undefined`. (code: validation_error, status: 400)

I think the structure is correct, so I'm thinking there's probably something wrong with the code.

Thank you .

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.