Skip to content

Commit cd89812

Browse files
committed
feat: implement append block children
1 parent 30e07d0 commit cd89812

File tree

7 files changed

+165
-54
lines changed

7 files changed

+165
-54
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ go get -u github.com/mkfsn/notion-go
2626
* [x] Retrieve ✅
2727
* [ ] Create ❌
2828
* [ ] Update ❌
29-
- [ ] Blocks
30-
* [ ] Children ⚠️
29+
- [x] Blocks
30+
* [x] Children
3131
- [x] Retrieve ✅
32-
- [ ] Append
32+
- [x] Append
3333
- [x] Search ✅

blocks.go

+64-31
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package notion
33
import (
44
"context"
55
"encoding/json"
6-
"fmt"
76
"net/http"
87
"strings"
98
"time"
@@ -31,7 +30,7 @@ func newBlock(data []byte) (Block, error) {
3130
return block, nil
3231

3332
case BlockTypeHeading1:
34-
var block Heading3Block
33+
var block Heading1Block
3534

3635
if err := json.Unmarshal(data, &block); err != nil {
3736
return nil, err
@@ -40,7 +39,7 @@ func newBlock(data []byte) (Block, error) {
4039
return block, nil
4140

4241
case BlockTypeHeading2:
43-
var block Heading3Block
42+
var block Heading2Block
4443

4544
if err := json.Unmarshal(data, &block); err != nil {
4645
return nil, err
@@ -132,70 +131,83 @@ const (
132131

133132
type BlockBase struct {
134133
// Always "block".
135-
Object string `json:"object"`
134+
Object ObjectType `json:"object"`
136135
// Identifier for the block.
137-
ID string `json:"id"`
136+
ID string `json:"id,omitempty"`
138137
// Type of block.
139138
Type BlockType `json:"type"`
140139
// Date and time when this block was created. Formatted as an ISO 8601 date time string.
141-
CreatedTime time.Time `json:"created_time"`
140+
CreatedTime *time.Time `json:"created_time,omitempty"`
142141
// Date and time when this block was last updated. Formatted as an ISO 8601 date time string.
143-
LastEditedTime time.Time `json:"last_edited_time"`
142+
LastEditedTime *time.Time `json:"last_edited_time,omitempty"`
144143
// Whether or not the block has children blocks nested within it.
145-
HasChildren bool `json:"has_children"`
144+
HasChildren *bool `json:"has_children,omitempty"`
146145
}
147146

148147
func (b BlockBase) isBlock() {}
149148

150149
type ParagraphBlock struct {
151150
BlockBase
152-
Text []RichText `json:"text"`
153-
Children []BlockBase `json:"children"`
151+
Paragraph RichTextBlock `json:"paragraph"`
154152
}
155153

156-
type Heading3Block struct {
157-
BlockBase
154+
type HeadingBlock struct {
158155
Text []RichText `json:"text"`
159156
}
160157

161-
type HeadingTwoBlock struct {
158+
type Heading1Block struct {
162159
BlockBase
163-
Text []RichText `json:"text"`
160+
Heading1 HeadingBlock `json:"heading_1"`
164161
}
165162

166-
type HeadingThreeBlock struct {
163+
type Heading2Block struct {
167164
BlockBase
168-
Text []RichText `json:"text"`
165+
Heading2 HeadingBlock `json:"heading_2"`
169166
}
170167

171-
type BulletedListItemBlock struct {
168+
type Heading3Block struct {
172169
BlockBase
170+
Heading3 HeadingBlock `json:"heading_3"`
171+
}
172+
173+
type RichTextBlock struct {
173174
Text []RichText `json:"text"`
174-
Children []BlockBase `json:"children"`
175+
Children []BlockBase `json:"children,omitempty"`
176+
}
177+
178+
type BulletedListItemBlock struct {
179+
BlockBase
180+
BulletedListItem RichTextBlock `json:"bulleted_list_item"`
175181
}
176182

177183
type NumberedListItemBlock struct {
178184
BlockBase
185+
NumberedListItem RichTextBlock `json:"numbered_list_item"`
186+
}
187+
188+
type RichTextWithCheckBlock struct {
179189
Text []RichText `json:"text"`
190+
Checked bool `json:"checked"`
180191
Children []BlockBase `json:"children"`
181192
}
182193

183194
type ToDoBlock struct {
184195
BlockBase
185-
Text []RichText `json:"text"`
186-
Checked bool `json:"checked"`
187-
Children []BlockBase `json:"children"`
196+
ToDo RichTextWithCheckBlock `json:"todo"`
188197
}
189198

190199
type ToggleBlock struct {
191200
BlockBase
192-
Text []RichText `json:"text"`
193-
Children []BlockBase `json:"children"`
201+
Toggle RichTextBlock `json:"toggle"`
202+
}
203+
204+
type TitleBlock struct {
205+
Title string `json:"title"`
194206
}
195207

196208
type ChildPageBlock struct {
197209
BlockBase
198-
Title string `json:"title"`
210+
ChildPage TitleBlock `json:"child_page"`
199211
}
200212

201213
type UnsupportedBlock struct {
@@ -264,14 +276,24 @@ func (b *BlocksChildrenListResponse) UnmarshalJSON(data []byte) error {
264276

265277
type BlocksChildrenAppendParameters struct {
266278
// Identifier for a block
267-
BlockID string
279+
BlockID string `json:"-" url:"-"`
268280
// Child content to append to a container block as an array of block objects
269-
Children []Block `json:"children"`
281+
Children []Block `json:"children" url:"-"`
270282
}
271283

272284
type BlocksChildrenAppendResponse struct {
273-
// TODO: check if this is correct
274-
BlockBase
285+
Block
286+
}
287+
288+
func (b *BlocksChildrenAppendResponse) UnmarshalJSON(data []byte) error {
289+
block, err := newBlock(data)
290+
if err != nil {
291+
return err
292+
}
293+
294+
b.Block = block
295+
296+
return nil
275297
}
276298

277299
type BlocksChildrenInterface interface {
@@ -292,8 +314,6 @@ func newBlocksChildrenClient(client client) *blocksChildrenClient {
292314
func (b *blocksChildrenClient) List(ctx context.Context, params BlocksChildrenListParameters) (*BlocksChildrenListResponse, error) {
293315
endpoint := strings.Replace(APIBlocksListChildrenEndpoint, "{block_id}", params.BlockID, 1)
294316

295-
fmt.Printf("endpoint: %s\n", endpoint)
296-
297317
data, err := b.client.Request(ctx, http.MethodGet, endpoint, nil)
298318
if err != nil {
299319
return nil, err
@@ -309,5 +329,18 @@ func (b *blocksChildrenClient) List(ctx context.Context, params BlocksChildrenLi
309329
}
310330

311331
func (b *blocksChildrenClient) Append(ctx context.Context, params BlocksChildrenAppendParameters) (*BlocksChildrenAppendResponse, error) {
312-
return nil, ErrUnimplemented
332+
endpoint := strings.Replace(APIBlocksAppendChildrenEndpoint, "{block_id}", params.BlockID, 1)
333+
334+
data, err := b.client.Request(ctx, http.MethodPatch, endpoint, params)
335+
if err != nil {
336+
return nil, err
337+
}
338+
339+
var response BlocksChildrenAppendResponse
340+
341+
if err := json.Unmarshal(data, &response); err != nil {
342+
return nil, err
343+
}
344+
345+
return &response, nil
313346
}

databases.go

+18-16
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
)
1010

1111
type Database struct {
12-
Object string `json:"object"`
13-
ID string `json:"id"`
12+
Object ObjectType `json:"object"`
13+
ID string `json:"id"`
1414

1515
CreatedTime time.Time `json:"created_time"`
1616
LastEditedTime time.Time `json:"last_edited_time"`
@@ -39,7 +39,7 @@ func (d *Database) UnmarshalJSON(data []byte) error {
3939
d.Properties = make(map[string]Property)
4040

4141
for _, title := range alias.Title {
42-
var base baseRichText
42+
var base BaseRichText
4343

4444
if err := json.Unmarshal(title, &base); err != nil {
4545
return err
@@ -279,7 +279,7 @@ type RichText interface {
279279
}
280280

281281
func newRichText(data []byte) (RichText, error) {
282-
var base baseRichText
282+
var base BaseRichText
283283

284284
if err := json.Unmarshal(data, &base); err != nil {
285285
return nil, err
@@ -325,30 +325,32 @@ const (
325325
RichTextTypeEquation RichTextType = "equation"
326326
)
327327

328-
type baseRichText struct {
328+
type BaseRichText struct {
329329
// The plain text without annotations.
330-
PlainText string `json:"plain_text"`
330+
PlainText string `json:"plain_text,omitempty"`
331331
// (Optional) The URL of any link or internal Notion mention in this text, if any.
332-
Href string `json:"href"`
332+
Href string `json:"href,omitempty"`
333333
// Type of this rich text object.
334334
Type RichTextType `json:"type"`
335335
// All annotations that apply to this rich text.
336336
// Annotations include colors and bold/italics/underline/strikethrough.
337-
Annotations Annotations `json:"annotations"`
337+
Annotations *Annotations `json:"annotations,omitempty"`
338338
}
339339

340-
func (r baseRichText) isRichText() {}
340+
func (r BaseRichText) isRichText() {}
341+
342+
type Link struct {
343+
Type string `json:"type"`
344+
URL string `json:"url"`
345+
}
341346

342347
type TextObject struct {
343348
Content string `json:"content"`
344-
Link *struct {
345-
Type string `json:"type"`
346-
URL string `json:"url"`
347-
} `json:"link"`
349+
Link *Link `json:"link,omitempty"`
348350
}
349351

350352
type RichTextText struct {
351-
baseRichText
353+
BaseRichText
352354
Text TextObject `json:"text"`
353355
}
354356

@@ -387,7 +389,7 @@ type DateMention struct {
387389
}
388390

389391
type RichTextMention struct {
390-
baseRichText
392+
BaseRichText
391393
Mention Mention `json:"mention"`
392394
}
393395

@@ -396,7 +398,7 @@ type EquationObject struct {
396398
}
397399

398400
type RichTextEquation struct {
399-
baseRichText
401+
BaseRichText
400402
Equation EquationObject `json:"equation"`
401403
}
402404

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
"os"
7+
8+
"github.com/mkfsn/notion-go"
9+
)
10+
11+
func main() {
12+
c := notion.New(notion.WithAuthToken(os.Getenv("NOTION_AUTH_TOKEN")))
13+
14+
resp, err := c.Blocks().Children().Append(context.Background(),
15+
notion.BlocksChildrenAppendParameters{
16+
BlockID: "12e1d803ee234651a125c6ce13ccd58d",
17+
Children: []notion.Block{
18+
notion.Heading2Block{
19+
BlockBase: notion.BlockBase{
20+
Object: notion.ObjectTypeBlock,
21+
Type: notion.BlockTypeHeading2,
22+
},
23+
Heading2: notion.HeadingBlock{
24+
Text: []notion.RichText{
25+
notion.RichTextText{
26+
BaseRichText: notion.BaseRichText{
27+
Type: notion.RichTextTypeText,
28+
},
29+
Text: notion.TextObject{
30+
Content: "Lacinato kale",
31+
},
32+
},
33+
},
34+
},
35+
},
36+
37+
notion.ParagraphBlock{
38+
BlockBase: notion.BlockBase{
39+
Object: notion.ObjectTypeBlock,
40+
Type: notion.BlockTypeParagraph,
41+
},
42+
Paragraph: notion.RichTextBlock{
43+
Text: []notion.RichText{
44+
notion.RichTextText{
45+
BaseRichText: notion.BaseRichText{
46+
Type: notion.RichTextTypeText,
47+
},
48+
Text: notion.TextObject{
49+
Content: "Lacinato kale is a variety of kale with a long tradition in Italian cuisine, especially that of Tuscany. It is also known as Tuscan kale, Italian kale, dinosaur kale, kale, flat back kale, palm tree kale, or black Tuscan palm.",
50+
Link: &notion.Link{
51+
Type: "url",
52+
URL: "https://en.wikipedia.org/wiki/Lacinato_kale",
53+
},
54+
},
55+
},
56+
},
57+
},
58+
},
59+
},
60+
},
61+
)
62+
63+
if err != nil {
64+
log.Fatal(err)
65+
}
66+
67+
log.Printf("response: %#v\n", resp)
68+
}

pages.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ type PageParentInput struct {
6060

6161
type Page struct {
6262
// Always "page".
63-
Object string `json:"object"`
63+
Object ObjectType `json:"object"`
6464
// Unique identifier of the page.
6565
ID string `json:"id"`
6666
// The page's parent

search.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ func (s *SearchResponse) UnmarshalJSON(data []byte) error {
8484

8585
for _, result := range alias.Results {
8686
var base struct {
87-
Object string `json:"object"`
87+
Object ObjectType `json:"object"`
8888
}
8989

9090
if err := json.Unmarshal(result, &base); err != nil {
9191
return err
9292
}
9393

9494
switch base.Object {
95-
case "page":
95+
case ObjectTypePage:
9696
var object Page
9797

9898
if err := json.Unmarshal(result, &object); err != nil {
@@ -101,7 +101,7 @@ func (s *SearchResponse) UnmarshalJSON(data []byte) error {
101101

102102
s.Results = append(s.Results, object)
103103

104-
case "database":
104+
case ObjectTypeDatabase:
105105
var object Database
106106

107107
if err := json.Unmarshal(result, &object); err != nil {

0 commit comments

Comments
 (0)