notion 1.0.6 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -4
- data/lib/notion_api/core.rb +128 -99
- data/lib/notion_api/notion_types/code_block.rb +13 -13
- data/lib/notion_api/notion_types/collection_view_blocks.rb +72 -36
- data/lib/notion_api/notion_types/column_list_block.rb +13 -13
- data/lib/notion_api/notion_types/divider_block.rb +13 -13
- data/lib/notion_api/notion_types/header_block.rb +13 -13
- data/lib/notion_api/notion_types/image_block.rb +59 -12
- data/lib/notion_api/notion_types/latex_block.rb +13 -13
- data/lib/notion_api/notion_types/numbered_block.rb +13 -13
- data/lib/notion_api/notion_types/page_block.rb +117 -124
- data/lib/notion_api/notion_types/quote_block.rb +13 -13
- data/lib/notion_api/notion_types/sub_header_block.rb +13 -13
- data/lib/notion_api/notion_types/sub_sub_header.rb +13 -13
- data/lib/notion_api/notion_types/table_of_contents_block.rb +3 -3
- data/lib/notion_api/notion_types/template.rb +325 -328
- data/lib/notion_api/notion_types/text_block.rb +13 -13
- data/lib/notion_api/notion_types/todo_block.rb +56 -56
- data/lib/notion_api/notion_types/toggle_block.rb +13 -13
- data/lib/notion_api/utils.rb +175 -76
- data/lib/notion_api/version.rb +1 -1
- metadata +6 -6
@@ -1,16 +1,16 @@
|
|
1
1
|
module NotionAPI
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
# good for just about anything (-:
|
4
|
+
class TextBlock < BlockTemplate
|
5
|
+
@notion_type = "text"
|
6
|
+
@type = "text"
|
7
|
+
|
8
|
+
def type
|
9
|
+
NotionAPI::TextBlock.notion_type
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :notion_type, :type
|
15
14
|
end
|
16
|
-
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,60 +1,60 @@
|
|
1
1
|
module NotionAPI
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
Please try again, and if issues persist open an issue in GitHub.";
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
3
|
+
# To-Do block: best for checklists and tracking to-dos.
|
4
|
+
class TodoBlock < BlockTemplate
|
5
|
+
@notion_type = "to_do"
|
6
|
+
@type = "to_do"
|
7
|
+
|
8
|
+
def type
|
9
|
+
NotionAPI::TodoBlock.notion_type
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :notion_type, :type
|
14
|
+
end
|
15
|
+
|
16
|
+
def checked=(checked_value)
|
17
|
+
# ! change the checked property of the Todo Block.
|
18
|
+
# ! checked_value -> boolean value used to determine whether the block should be checked [yes] or not [no] : ``str``
|
19
|
+
# set static variables for request
|
20
|
+
cookies = Core.options["cookies"]
|
21
|
+
headers = Core.options["headers"]
|
22
|
+
request_url = URLS[:UPDATE_BLOCK]
|
23
|
+
|
24
|
+
# set unique values for request
|
25
|
+
request_id = extract_id(SecureRandom.hex(16))
|
26
|
+
transaction_id = extract_id(SecureRandom.hex(16))
|
27
|
+
space_id = extract_id(SecureRandom.hex(16))
|
28
|
+
request_ids = {
|
29
|
+
request_id: request_id,
|
30
|
+
transaction_id: transaction_id,
|
31
|
+
space_id: space_id,
|
32
|
+
}
|
33
|
+
|
34
|
+
if %w[yes no].include?(checked_value.downcase)
|
35
|
+
checked_hash = Utils::BlockComponents.checked_todo(@id, checked_value.downcase)
|
36
|
+
last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(@parent_id)
|
37
|
+
last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
|
38
|
+
|
39
|
+
operations = [
|
40
|
+
checked_hash,
|
41
|
+
last_edited_time_parent_hash,
|
42
|
+
last_edited_time_child_hash,
|
43
|
+
]
|
44
|
+
request_body = build_payload(operations, request_ids)
|
45
|
+
response = HTTParty.post(
|
46
|
+
request_url,
|
47
|
+
body: request_body.to_json,
|
48
|
+
cookies: cookies,
|
49
|
+
headers: headers,
|
50
|
+
)
|
51
|
+
unless response.code == 200; raise "There was an issue completing your request. Here is the response from Notion: #{response.body}, and here is the payload that was sent: #{operations}.
|
52
|
+
Please try again, and if issues persist open an issue in GitHub."; end
|
53
|
+
|
54
|
+
true
|
55
|
+
else
|
56
|
+
false
|
58
57
|
end
|
59
58
|
end
|
60
|
-
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module NotionAPI
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
# Toggle block: best for storing children blocks
|
4
|
+
class ToggleBlock < BlockTemplate
|
5
|
+
@notion_type = "toggle"
|
6
|
+
@type = "toggle"
|
7
|
+
|
8
|
+
def type
|
9
|
+
NotionAPI::ToggleBlock.notion_type
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :notion_type, :type
|
15
14
|
end
|
16
|
-
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/notion_api/utils.rb
CHANGED
@@ -11,6 +11,27 @@ module Utils
|
|
11
11
|
class BlockComponents
|
12
12
|
# ! Each function defined here builds one component that is included in each request sent to Notions backend.
|
13
13
|
# ! Each request sent will contain multiple components.
|
14
|
+
# TODO figure this out
|
15
|
+
def self.build_payload(operations, request_ids)
|
16
|
+
# ! properly formats the payload for Notions backend.
|
17
|
+
# ! operations -> an array of hashes that define the operations to perform : ``Array[Hash]``
|
18
|
+
# ! request_ids -> the unique IDs for the request : ``str``
|
19
|
+
request_id = request_ids[:request_id]
|
20
|
+
transaction_id = request_ids[:transaction_id]
|
21
|
+
space_id = request_ids[:space_id]
|
22
|
+
payload = {
|
23
|
+
requestId: request_id,
|
24
|
+
transactions: [
|
25
|
+
{
|
26
|
+
id: transaction_id,
|
27
|
+
shardId: 955_090,
|
28
|
+
spaceId: space_id,
|
29
|
+
operations: operations,
|
30
|
+
},
|
31
|
+
],
|
32
|
+
}
|
33
|
+
payload
|
34
|
+
end
|
14
35
|
def self.create(block_id, block_type)
|
15
36
|
# ! payload for creating a block.
|
16
37
|
# ! block_id -> id of the new block : ``str``
|
@@ -200,14 +221,14 @@ module Utils
|
|
200
221
|
|
201
222
|
args = if command == "listAfter"
|
202
223
|
{
|
203
|
-
|
204
|
-
|
205
|
-
|
224
|
+
after: target || block_id,
|
225
|
+
id: new_block_id || block_id,
|
226
|
+
}
|
206
227
|
else
|
207
228
|
{
|
208
|
-
|
209
|
-
|
210
|
-
|
229
|
+
before: target || block_id,
|
230
|
+
id: new_block_id || block_id,
|
231
|
+
}
|
211
232
|
end
|
212
233
|
|
213
234
|
{
|
@@ -219,6 +240,25 @@ module Utils
|
|
219
240
|
}
|
220
241
|
end
|
221
242
|
|
243
|
+
def self.row_location_add(last_row_id, block_id, view_id)
|
244
|
+
# ! add a new row to a Collection View table
|
245
|
+
# ! last_row_id -> ID of the last row in the CV : ``str``
|
246
|
+
# ! block_id -> ID of the blow : ``str``
|
247
|
+
# ! view_id -> ID of the View : ``str``
|
248
|
+
{
|
249
|
+
"table": "collection_view",
|
250
|
+
"id": view_id,
|
251
|
+
"path": [
|
252
|
+
"page_sort",
|
253
|
+
],
|
254
|
+
"command": "listAfter",
|
255
|
+
"args": {
|
256
|
+
"after": last_row_id,
|
257
|
+
"id": block_id,
|
258
|
+
},
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
222
262
|
def self.block_location_remove(block_parent_id, block_id)
|
223
263
|
# ! removes a notion block
|
224
264
|
# ! block_parent_id -> the parent ID of the block to remove : ``str``
|
@@ -274,11 +314,52 @@ module Utils
|
|
274
314
|
}
|
275
315
|
end
|
276
316
|
def self.add_emoji_icon(block_id, icon)
|
317
|
+
# ! add an emoji icon for either a page or callout block
|
318
|
+
# ! block_id -> the ID of the block : ``str``
|
319
|
+
# ! icon -> the icon for the block. This is currently randomly chosen. : ``str``
|
277
320
|
{
|
278
321
|
id: block_id,
|
279
|
-
table:"block",
|
280
|
-
path:["format","page_icon"],
|
281
|
-
command:"set","args": icon
|
322
|
+
table: "block",
|
323
|
+
path: ["format", "page_icon"],
|
324
|
+
command: "set", "args": icon,
|
325
|
+
}
|
326
|
+
end
|
327
|
+
|
328
|
+
def self.source(new_block_id, url)
|
329
|
+
# ! set the source for the ImageBlock
|
330
|
+
# ! new_block_id -> the ID of the new ImageBlock: ``str``
|
331
|
+
# ! url -> the URL for the image
|
332
|
+
table = "block"
|
333
|
+
path = ["properties"]
|
334
|
+
command = "update"
|
335
|
+
|
336
|
+
{
|
337
|
+
id: new_block_id,
|
338
|
+
table: table,
|
339
|
+
path: path,
|
340
|
+
command: command,
|
341
|
+
args: {
|
342
|
+
source: [[
|
343
|
+
url,
|
344
|
+
]],
|
345
|
+
},
|
346
|
+
}
|
347
|
+
end
|
348
|
+
|
349
|
+
def self.display_source(new_block_id, block_url)
|
350
|
+
# ! set the display source for the ImageBlock
|
351
|
+
# ! new_block_id -> the ID of the new ImageBlock: ``str``
|
352
|
+
# ! block_url -> the URL of the ImageBlock: ``str``
|
353
|
+
{
|
354
|
+
"id": new_block_id,
|
355
|
+
"table": "block",
|
356
|
+
"path": [
|
357
|
+
"format",
|
358
|
+
],
|
359
|
+
"command": "update",
|
360
|
+
"args": {
|
361
|
+
"display_source": block_url,
|
362
|
+
},
|
282
363
|
}
|
283
364
|
end
|
284
365
|
end
|
@@ -383,14 +464,14 @@ module Utils
|
|
383
464
|
# ! new_block_id -> id of the new block
|
384
465
|
# ! data -> json data to insert into table.
|
385
466
|
col_names = data[0].keys
|
386
|
-
data_mappings = {Integer => "number", String => "text", Array => "text", Float => "number", Date => "date"}
|
467
|
+
data_mappings = { Integer => "number", String => "text", Array => "text", Float => "number", Date => "date" }
|
387
468
|
exceptions = [ArgumentError, TypeError]
|
388
469
|
data_types = col_names.map do |name|
|
389
470
|
# TODO: this is a little hacky... should probably think about a better way or add a requirement for user input to match a certain criteria.
|
390
|
-
begin
|
471
|
+
begin
|
391
472
|
DateTime.parse(data[0][name]) ? data_mappings[Date] : nil
|
392
473
|
rescue *exceptions
|
393
|
-
data_mappings[data[0][name].class]
|
474
|
+
data_mappings[data[0][name].class]
|
394
475
|
end
|
395
476
|
end
|
396
477
|
|
@@ -403,18 +484,18 @@ module Utils
|
|
403
484
|
end
|
404
485
|
end
|
405
486
|
return {
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
487
|
+
id: collection_id,
|
488
|
+
table: "collection",
|
489
|
+
path: [],
|
490
|
+
command: "update",
|
491
|
+
args: {
|
492
|
+
id: collection_id,
|
493
|
+
schema: schema_conf,
|
494
|
+
parent_id: new_block_id,
|
495
|
+
parent_table: "block",
|
496
|
+
alive: true,
|
497
|
+
},
|
498
|
+
}, data_types
|
418
499
|
end
|
419
500
|
|
420
501
|
def self.set_collection_title(collection_title, collection_id)
|
@@ -440,6 +521,12 @@ module Utils
|
|
440
521
|
# ! column -> the name of the column to insert data into.
|
441
522
|
# ! value -> the value to insert into the column.
|
442
523
|
# ! mapping -> the column data type.
|
524
|
+
simple_mappings = ["title", "text", "phone_number", "email", "url", "number", "checkbox", "select", "multi_select"]
|
525
|
+
datetime_mappings = ["date"]
|
526
|
+
media_mappings = ["file"]
|
527
|
+
person_mappings = ["person"]
|
528
|
+
page_mappings = ["relation"]
|
529
|
+
|
443
530
|
table = "block"
|
444
531
|
path = [
|
445
532
|
"properties",
|
@@ -447,12 +534,52 @@ module Utils
|
|
447
534
|
]
|
448
535
|
command = "set"
|
449
536
|
|
537
|
+
if simple_mappings.include?(mapping)
|
538
|
+
args = [[value]]
|
539
|
+
elsif media_mappings.include?(mapping)
|
540
|
+
args = [[value, [["a", value]]]]
|
541
|
+
elsif datetime_mappings.include?(mapping)
|
542
|
+
args = [["‣", [["d", { "type": "date", "start_date": value }]]]]
|
543
|
+
elsif person_mappings.include?(mapping)
|
544
|
+
args = [["‣",
|
545
|
+
[["u", value]]]]
|
546
|
+
elsif page_mappings.include?(mapping)
|
547
|
+
args = [["‣",
|
548
|
+
[["p", value]]]]
|
549
|
+
else
|
550
|
+
raise SchemaTypeError, "Invalid property type: #{mapping}"
|
551
|
+
end
|
552
|
+
|
450
553
|
{
|
451
|
-
id: block_id,
|
452
554
|
table: table,
|
555
|
+
id: block_id,
|
556
|
+
command: command,
|
453
557
|
path: path,
|
558
|
+
args: args,
|
559
|
+
}
|
560
|
+
end
|
561
|
+
|
562
|
+
def self.add_new_option(column, value, collection_id)
|
563
|
+
table = "collection"
|
564
|
+
path = ["schema", column, "options"]
|
565
|
+
command = "keyedObjectListAfter"
|
566
|
+
colors = ["default", "gray", "brown", "orange", "yellow", "green", "blue", "purple", "pink", "red"]
|
567
|
+
random_color = colors[rand(0...colors.length)]
|
568
|
+
|
569
|
+
args = {
|
570
|
+
"value": {
|
571
|
+
"id": SecureRandom.hex(16),
|
572
|
+
"value": value,
|
573
|
+
"color": random_color,
|
574
|
+
},
|
575
|
+
}
|
576
|
+
|
577
|
+
{
|
578
|
+
table: table,
|
579
|
+
id: collection_id,
|
454
580
|
command: command,
|
455
|
-
|
581
|
+
path: path,
|
582
|
+
args: args,
|
456
583
|
}
|
457
584
|
end
|
458
585
|
|
@@ -502,50 +629,7 @@ module Utils
|
|
502
629
|
# ! payload for adding a column to the table.
|
503
630
|
# ! collection_id -> the collection ID : ``str``
|
504
631
|
# ! args -> the definition of the column : ``str``
|
505
|
-
|
506
|
-
"table_properties" => [
|
507
|
-
{
|
508
|
-
"property" => "title",
|
509
|
-
"visible" => true,
|
510
|
-
"width" => 280,
|
511
|
-
},
|
512
|
-
{
|
513
|
-
"property" => "aliases",
|
514
|
-
"visible" => true,
|
515
|
-
"width" => 200,
|
516
|
-
},
|
517
|
-
{
|
518
|
-
"property" => "category",
|
519
|
-
"visible" => true,
|
520
|
-
"width" => 200,
|
521
|
-
},
|
522
|
-
{
|
523
|
-
"property" => "description",
|
524
|
-
"visible" => true,
|
525
|
-
"width" => 200,
|
526
|
-
},
|
527
|
-
{
|
528
|
-
"property" => "ios_version",
|
529
|
-
"visible" => true,
|
530
|
-
"width" => 200,
|
531
|
-
},
|
532
|
-
{
|
533
|
-
"property" => "tags",
|
534
|
-
"visible" => true,
|
535
|
-
"width" => 200,
|
536
|
-
},
|
537
|
-
{
|
538
|
-
"property" => "phone",
|
539
|
-
"visible" => true,
|
540
|
-
"width" => 200,
|
541
|
-
},
|
542
|
-
{
|
543
|
-
"property" => "unicode_version",
|
544
|
-
"visible" => true,
|
545
|
-
"width" => 200,
|
546
|
-
}
|
547
|
-
],
|
548
|
-
}
|
632
|
+
|
549
633
|
{
|
550
634
|
id: collection_id,
|
551
635
|
table: "collection",
|
@@ -555,31 +639,46 @@ module Utils
|
|
555
639
|
}
|
556
640
|
end
|
557
641
|
|
558
|
-
def self.update_property_value(page_id, column_name, new_value)
|
642
|
+
def self.update_property_value(page_id, column_name, new_value, column_type)
|
559
643
|
# ! update the specified column_name to new_value
|
560
644
|
# ! page_id -> the ID of the page: ``str``
|
561
645
|
# ! column_name -> the name of the column ["property"] to update: ``str``
|
562
646
|
# ! new_value -> the new value to assign to that column ["property"]: ``str``
|
647
|
+
# ! column_type -> the type of the property: ``str``
|
563
648
|
table = "block"
|
564
649
|
path = [
|
565
650
|
"properties",
|
566
|
-
column_name
|
651
|
+
column_name,
|
567
652
|
]
|
568
653
|
command = "set"
|
569
|
-
|
570
|
-
|
571
|
-
|
654
|
+
|
655
|
+
if column_type == "relation"
|
656
|
+
args = [["‣", [[
|
657
|
+
"p", new_value,
|
658
|
+
]]]]
|
659
|
+
else
|
660
|
+
args = [[
|
661
|
+
new_value,
|
662
|
+
]]
|
663
|
+
end
|
572
664
|
|
573
665
|
{
|
574
666
|
id: page_id,
|
575
667
|
table: table,
|
576
668
|
path: path,
|
577
669
|
command: command,
|
578
|
-
args: args
|
670
|
+
args: args,
|
579
671
|
}
|
580
672
|
end
|
581
673
|
end
|
582
674
|
|
675
|
+
class SchemaTypeError < StandardError
|
676
|
+
def initialize(msg = "Custom exception that is raised when an invalid property type is passed as a mapping.", exception_type = "schema_type")
|
677
|
+
@exception_type = exception_type
|
678
|
+
super(msg)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
583
682
|
def build_payload(operations, request_ids)
|
584
683
|
# ! properly formats the payload for Notions backend.
|
585
684
|
# ! operations -> an array of hashes that define the operations to perform : ``Array[Hash]``
|