notion 1.0.5 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -4
- data/lib/notion_api/core.rb +13 -4
- data/lib/notion_api/notion_types/collection_view_blocks.rb +61 -13
- data/lib/notion_api/utils.rb +124 -59
- data/lib/notion_api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3114ccf59f80a17322c559fce61050e7e7f1908a279e8786c4a8fe87e6fa79d8
|
4
|
+
data.tar.gz: a7c6fea5eb18a4d962117a4a5120bc357e0bf038640ba39db821d5bc3de230e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz: '
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '06202342711853b35c0d694b4de7c89aec269f226d5ceda2c6b4e086f61f6e8f3e7381ca1d0389d85c2b3814d849dd980d9d6b3492a9d2a3d9c8bf9fbad71939'
|
7
|
+
data.tar.gz: 7561a58fff0a26b4190a79c713a4f89c3f85c1c5cca4bca21e2c9013ea3fa981f32e8779e9b771b243fe41a65c5b717f9a09e675e9c9590c3a09cf1f344ca02b
|
data/README.md
CHANGED
@@ -310,8 +310,12 @@ From here, you can instantiate the Notion Client with the following code:
|
|
310
310
|
)
|
311
311
|
```
|
312
312
|
### Retrieve a full-page Collection View
|
313
|
-
|
314
|
-
|
315
|
-
|
313
|
+
A full-page collection view must have a URL that follows the below pattern:
|
314
|
+
https://www.notion.so/danmurphy/[page-id]?v=[view-id]
|
315
|
+
Then, it can be retrieved with the following code:
|
316
|
+
```ruby
|
317
|
+
>>> @client = NotionAPI::Client.new(
|
318
|
+
"<insert_v2_token_here>"
|
319
|
+
)
|
320
|
+
>>> @client.get_page(https://www.notion.so/danmurphy/[page-id]?v=[view-id])
|
316
321
|
```
|
317
|
-
To avoid this, you must pass only the ID of the full-page collection-view to the `get_page` method. This is next up on the features list, so passing the full URL will be supported soon:smile:
|
data/lib/notion_api/core.rb
CHANGED
@@ -235,17 +235,26 @@ module NotionAPI
|
|
235
235
|
# ! parse and clean the URL or ID object provided.
|
236
236
|
# ! url_or_id -> the block ID or URL : ``str``
|
237
237
|
http_or_https = url_or_id.match(/^(http|https)/) # true if http or https in url_or_id...
|
238
|
+
collection_view_match = url_or_id.match(/(\?v=)/)
|
239
|
+
|
238
240
|
if (url_or_id.length == 36) && ((url_or_id.split('-').length == 5) && !http_or_https)
|
239
241
|
# passes if url_or_id is perfectly formatted already...
|
240
242
|
url_or_id
|
241
|
-
elsif (http_or_https && (url_or_id.split('-').last.length == 32)) || (!http_or_https && (url_or_id.length == 32))
|
243
|
+
elsif (http_or_https && (url_or_id.split('-').last.length == 32)) || (!http_or_https && (url_or_id.length == 32)) || (collection_view_match)
|
242
244
|
# passes if either:
|
243
245
|
# 1. a URL is passed as url_or_id and the ID at the end is 32 characters long or
|
244
246
|
# 2. a URL is not passed and the ID length is 32 [aka unformatted]
|
245
247
|
pattern = [8, 13, 18, 23]
|
246
|
-
|
247
|
-
|
248
|
-
|
248
|
+
if collection_view_match
|
249
|
+
id_without_view = url_or_id.split('?')[0]
|
250
|
+
clean_id = id_without_view.split('/').last
|
251
|
+
pattern.each { |index| clean_id.insert(index, '-') }
|
252
|
+
clean_id
|
253
|
+
else
|
254
|
+
id = url_or_id.split('-').last
|
255
|
+
pattern.each { |index| id.insert(index, '-') }
|
256
|
+
id
|
257
|
+
end
|
249
258
|
else
|
250
259
|
raise ArgumentError, 'Expected a Notion page URL or a page ID. Please consult the documentation for further information.'
|
251
260
|
end
|
@@ -33,7 +33,9 @@ module NotionAPI
|
|
33
33
|
transaction_id = extract_id(SecureRandom.hex(16))
|
34
34
|
space_id = extract_id(SecureRandom.hex(16))
|
35
35
|
new_block_id = extract_id(SecureRandom.hex(16))
|
36
|
-
|
36
|
+
collection_data = extract_collection_data(collection_id, view_id)
|
37
|
+
last_row_id = collection_data["collection_view"][@view_id]["value"]["page_sort"][-1]
|
38
|
+
schema = collection_data["collection"][collection_id]["value"]["schema"]
|
37
39
|
keys = schema.keys
|
38
40
|
col_map = {}
|
39
41
|
keys.map { |key| col_map[schema[key]["name"]] = key }
|
@@ -47,17 +49,28 @@ module NotionAPI
|
|
47
49
|
instantiate_row = Utils::CollectionViewComponents.add_new_row(new_block_id)
|
48
50
|
set_block_alive = Utils::CollectionViewComponents.set_collection_blocks_alive(new_block_id, @collection_id)
|
49
51
|
new_block_edited_time = Utils::BlockComponents.last_edited_time(new_block_id)
|
50
|
-
|
52
|
+
page_sort = Utils::BlockComponents.row_location_add(last_row_id, new_block_id, @view_id)
|
51
53
|
|
52
54
|
operations = [
|
53
55
|
instantiate_row,
|
54
56
|
set_block_alive,
|
55
57
|
new_block_edited_time,
|
56
|
-
|
58
|
+
page_sort,
|
57
59
|
]
|
58
60
|
|
59
61
|
data.keys.each_with_index do |col_name, j|
|
60
|
-
|
62
|
+
unless col_map.keys.include?(col_name.to_s); raise ArgumentError, "Column '#{col_name.to_s}' does not exist." end
|
63
|
+
if %q[select multi_select].include?(schema[col_map[col_name.to_s]]["type"])
|
64
|
+
options = schema[col_map[col_name.to_s]]["options"].nil? ? [] : schema[col_map[col_name.to_s]]["options"].map { |option| option["value"] }
|
65
|
+
multi_select_multi_options = data[col_name].split(",")
|
66
|
+
multi_select_multi_options.each do |option|
|
67
|
+
if !options.include?(option.strip)
|
68
|
+
create_new_option = Utils::CollectionViewComponents.add_new_option(col_map[col_name.to_s], option.strip, @collection_id)
|
69
|
+
operations.push(create_new_option)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
child_component = Utils::CollectionViewComponents.insert_data(new_block_id, col_map[col_name.to_s], data[col_name], schema[col_map[col_name.to_s]]["type"])
|
61
74
|
operations.push(child_component)
|
62
75
|
end
|
63
76
|
|
@@ -73,7 +86,18 @@ module NotionAPI
|
|
73
86
|
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}.
|
74
87
|
Please try again, and if issues persist open an issue in GitHub."; end
|
75
88
|
|
76
|
-
NotionAPI::CollectionViewRow.new(new_block_id, @parent_id, @collection_id, @view_id)
|
89
|
+
collection_row = NotionAPI::CollectionViewRow.new(new_block_id, @parent_id, @collection_id, @view_id)
|
90
|
+
|
91
|
+
properties = {}
|
92
|
+
data.keys.each do |col|
|
93
|
+
properties[col_map[col.to_s]] = [[data[col]]]
|
94
|
+
end
|
95
|
+
|
96
|
+
collection_data["block"][collection_row.id] = { "role" => "editor", "value" => { "id" => collection_row.id, "version" => 12, "type" => "page", "properties" => properties, "created_time" => 1607253360000, "last_edited_time" => 1607253360000, "parent_id" => "dde513c6-2428-4a5d-a830-7a67fdbf6b48", "parent_table" => "collection", "alive" => true, "created_by_table" => "notion_user", "created_by_id" => "0c5f02f3-495d-4b73-b1c5-9f6fe03a8c26", "last_edited_by_table" => "notion_user", "last_edited_by_id" => "0c5f02f3-495d-4b73-b1c5-9f6fe03a8c26", "shard_id" => 955090, "space_id" => "f687f7de-7f4c-4a86-b109-941a8dae92d2" } }
|
97
|
+
row_data = collection_data["block"][collection_row.id]
|
98
|
+
create_singleton_methods_and_instance_variables(collection_row, row_data)
|
99
|
+
|
100
|
+
collection_row
|
77
101
|
end
|
78
102
|
|
79
103
|
def add_property(name, type)
|
@@ -204,6 +228,7 @@ module NotionAPI
|
|
204
228
|
end
|
205
229
|
clean_row_instances
|
206
230
|
end
|
231
|
+
|
207
232
|
def create_singleton_methods_and_instance_variables(row, row_data)
|
208
233
|
# ! creates singleton methods for each property in a CollectionView.
|
209
234
|
# ! row -> the block ID of the 'row' to retrieve: ``str``
|
@@ -213,22 +238,25 @@ module NotionAPI
|
|
213
238
|
column_mappings = schema.keys
|
214
239
|
column_hash = {}
|
215
240
|
column_names = column_mappings.map { |mapping| column_hash[mapping] = schema[mapping]["name"].downcase }
|
216
|
-
|
241
|
+
|
217
242
|
column_hash.keys.each_with_index do |column, i|
|
218
243
|
# loop over the column names...
|
219
244
|
# set instance variables for each column, allowing the dev to 'read' the column value
|
220
|
-
cleaned_column = column_hash
|
245
|
+
cleaned_column = clean_property_names(column_hash, column)
|
221
246
|
|
222
247
|
# p row_data["value"]["properties"][column_mappings[i]], !(row_data["value"]["properties"][column] or row_data["value"]["properties"][column_mappings[i]])
|
223
248
|
if row_data["value"]["properties"].nil? or row_data["value"]["properties"][column].nil?
|
224
249
|
value = ""
|
225
250
|
else
|
226
|
-
value = row_data["value"]["properties"][column][0][0]
|
251
|
+
value = row_data["value"]["properties"][column][0][0]
|
252
|
+
if ["‣"].include?(value.to_s)
|
253
|
+
value = row_data["value"]["properties"][column][0][1].flatten[-1]
|
254
|
+
end
|
227
255
|
end
|
228
256
|
|
229
257
|
row.instance_variable_set("@#{cleaned_column}", value)
|
230
258
|
CollectionViewRow.class_eval { attr_reader cleaned_column }
|
231
|
-
# then, define singleton methods for each column that are used to update the table cell
|
259
|
+
# then, define singleton methods for each column that are used to update the table cell
|
232
260
|
row.define_singleton_method("#{cleaned_column}=") do |new_value|
|
233
261
|
# neat way to get the name of the currently invoked method...
|
234
262
|
parsed_method = __method__.to_s[0...-1].split("_").join(" ")
|
@@ -245,12 +273,23 @@ module NotionAPI
|
|
245
273
|
space_id: space_id,
|
246
274
|
}
|
247
275
|
|
248
|
-
|
276
|
+
update_property_value_hash = Utils::CollectionViewComponents.update_property_value(@id, column_hash.key(parsed_method), new_value)
|
249
277
|
|
250
278
|
operations = [
|
251
|
-
|
279
|
+
update_property_value_hash,
|
252
280
|
]
|
253
281
|
|
282
|
+
if %q[select multi_select].include?(schema[column_hash.key(parsed_method)]["type"])
|
283
|
+
options = schema[column_hash.key(parsed_method)]["options"].nil? ? [] : schema[column_hash.key(parsed_method)]["options"].map { |option| option["value"] }
|
284
|
+
multi_select_multi_options = new_value.split(",")
|
285
|
+
multi_select_multi_options.each do |option|
|
286
|
+
if !options.include?(option.strip)
|
287
|
+
create_new_option = Utils::CollectionViewComponents.add_new_option(column_hash.key(parsed_method), option.strip, @collection_id)
|
288
|
+
operations.push(create_new_option)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
254
293
|
request_url = URLS[:UPDATE_BLOCK]
|
255
294
|
request_body = build_payload(operations, request_ids)
|
256
295
|
response = HTTParty.post(
|
@@ -260,14 +299,23 @@ module NotionAPI
|
|
260
299
|
headers: headers,
|
261
300
|
)
|
262
301
|
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}.
|
263
|
-
Please try again, and if issues persist open an issue in GitHub.";end
|
264
|
-
|
302
|
+
Please try again, and if issues persist open an issue in GitHub."; end
|
303
|
+
|
265
304
|
# set the instance variable to the updated value!
|
266
305
|
_ = row.instance_variable_set("@#{__method__.to_s[0...-1]}", new_value)
|
267
306
|
row
|
268
307
|
end
|
269
308
|
end
|
270
309
|
end
|
310
|
+
|
311
|
+
def clean_property_names(prop_hash, prop_notion_name)
|
312
|
+
# ! standardize property names by splitting the words in the property name into an array, removing non-alphanumeric
|
313
|
+
# ! characters, downcasing, and then re-joining the array with underscores.
|
314
|
+
# ! prop_hash -> hash of property notion names and property textual names: ``str``
|
315
|
+
# ! prop_notion_name -> the four-character long name of the notion property: ``str``
|
316
|
+
|
317
|
+
prop_hash[prop_notion_name].split(" ").map { |word| word.gsub(/[^a-z0-9]/i, "").downcase }.join("_").to_sym
|
318
|
+
end
|
271
319
|
end
|
272
320
|
|
273
321
|
# class that represents each row in a CollectionView
|
data/lib/notion_api/utils.rb
CHANGED
@@ -200,14 +200,14 @@ module Utils
|
|
200
200
|
|
201
201
|
args = if command == "listAfter"
|
202
202
|
{
|
203
|
-
|
204
|
-
|
205
|
-
|
203
|
+
after: target || block_id,
|
204
|
+
id: new_block_id || block_id,
|
205
|
+
}
|
206
206
|
else
|
207
207
|
{
|
208
|
-
|
209
|
-
|
210
|
-
|
208
|
+
before: target || block_id,
|
209
|
+
id: new_block_id || block_id,
|
210
|
+
}
|
211
211
|
end
|
212
212
|
|
213
213
|
{
|
@@ -219,6 +219,21 @@ module Utils
|
|
219
219
|
}
|
220
220
|
end
|
221
221
|
|
222
|
+
def self.row_location_add(last_row_id, block_id, view_id)
|
223
|
+
{
|
224
|
+
"table": "collection_view",
|
225
|
+
"id": view_id,
|
226
|
+
"path": [
|
227
|
+
"page_sort"
|
228
|
+
],
|
229
|
+
"command": "listAfter",
|
230
|
+
"args": {
|
231
|
+
"after": last_row_id,
|
232
|
+
"id": block_id
|
233
|
+
}
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
222
237
|
def self.block_location_remove(block_parent_id, block_id)
|
223
238
|
# ! removes a notion block
|
224
239
|
# ! block_parent_id -> the parent ID of the block to remove : ``str``
|
@@ -276,9 +291,9 @@ module Utils
|
|
276
291
|
def self.add_emoji_icon(block_id, icon)
|
277
292
|
{
|
278
293
|
id: block_id,
|
279
|
-
table:"block",
|
280
|
-
path:["format","page_icon"],
|
281
|
-
command:"set","args": icon
|
294
|
+
table: "block",
|
295
|
+
path: ["format", "page_icon"],
|
296
|
+
command: "set", "args": icon,
|
282
297
|
}
|
283
298
|
end
|
284
299
|
end
|
@@ -383,14 +398,14 @@ module Utils
|
|
383
398
|
# ! new_block_id -> id of the new block
|
384
399
|
# ! data -> json data to insert into table.
|
385
400
|
col_names = data[0].keys
|
386
|
-
data_mappings = {Integer => "number", String => "text", Array => "text", Float => "number", Date => "date"}
|
401
|
+
data_mappings = { Integer => "number", String => "text", Array => "text", Float => "number", Date => "date" }
|
387
402
|
exceptions = [ArgumentError, TypeError]
|
388
403
|
data_types = col_names.map do |name|
|
389
404
|
# 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
|
405
|
+
begin
|
391
406
|
DateTime.parse(data[0][name]) ? data_mappings[Date] : nil
|
392
407
|
rescue *exceptions
|
393
|
-
data_mappings[data[0][name].class]
|
408
|
+
data_mappings[data[0][name].class]
|
394
409
|
end
|
395
410
|
end
|
396
411
|
|
@@ -403,18 +418,18 @@ module Utils
|
|
403
418
|
end
|
404
419
|
end
|
405
420
|
return {
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
421
|
+
id: collection_id,
|
422
|
+
table: "collection",
|
423
|
+
path: [],
|
424
|
+
command: "update",
|
425
|
+
args: {
|
426
|
+
id: collection_id,
|
427
|
+
schema: schema_conf,
|
428
|
+
parent_id: new_block_id,
|
429
|
+
parent_table: "block",
|
430
|
+
alive: true,
|
431
|
+
},
|
432
|
+
}, data_types
|
418
433
|
end
|
419
434
|
|
420
435
|
def self.set_collection_title(collection_title, collection_id)
|
@@ -440,6 +455,11 @@ module Utils
|
|
440
455
|
# ! column -> the name of the column to insert data into.
|
441
456
|
# ! value -> the value to insert into the column.
|
442
457
|
# ! mapping -> the column data type.
|
458
|
+
simple_mappings = ["title", "text", "phone_number", "email", "url", "number", "checkbox", "select", "multi_select"]
|
459
|
+
datetime_mappings = ["date"]
|
460
|
+
media_mappings = ["file"]
|
461
|
+
person_mappings = ["person"]
|
462
|
+
|
443
463
|
table = "block"
|
444
464
|
path = [
|
445
465
|
"properties",
|
@@ -447,12 +467,50 @@ module Utils
|
|
447
467
|
]
|
448
468
|
command = "set"
|
449
469
|
|
470
|
+
if simple_mappings.include?(mapping)
|
471
|
+
args = [[value]]
|
472
|
+
elsif media_mappings.include?(mapping)
|
473
|
+
args = [[value, [["a", value]]]]
|
474
|
+
elsif datetime_mappings.include?(mapping)
|
475
|
+
args = [["‣", [["d", { "type": "date", "start_date": value }]]]]
|
476
|
+
elsif person_mappings.include?(mapping)
|
477
|
+
args = [["‣",
|
478
|
+
[["u", value]]
|
479
|
+
]]
|
480
|
+
else
|
481
|
+
raise SchemaTypeError, "Invalid property type: #{mapping}"
|
482
|
+
end
|
483
|
+
|
450
484
|
{
|
451
|
-
id: block_id,
|
452
485
|
table: table,
|
486
|
+
id: block_id,
|
487
|
+
command: command,
|
453
488
|
path: path,
|
489
|
+
args: args,
|
490
|
+
}
|
491
|
+
end
|
492
|
+
|
493
|
+
def self.add_new_option(column, value, collection_id)
|
494
|
+
table = "collection"
|
495
|
+
path = ["schema", column, "options"]
|
496
|
+
command = "keyedObjectListAfter"
|
497
|
+
colors = ["default", "gray", "brown", "orange", "yellow", "green", "blue", "purple", "pink", "red"]
|
498
|
+
random_color = colors[rand(0...colors.length)]
|
499
|
+
|
500
|
+
args = {
|
501
|
+
"value": {
|
502
|
+
"id": SecureRandom.hex(16),
|
503
|
+
"value": value,
|
504
|
+
"color": random_color
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
{
|
509
|
+
table: table,
|
510
|
+
id: collection_id,
|
454
511
|
command: command,
|
455
|
-
|
512
|
+
path: path,
|
513
|
+
args: args,
|
456
514
|
}
|
457
515
|
end
|
458
516
|
|
@@ -505,45 +563,45 @@ module Utils
|
|
505
563
|
args["format"] = {
|
506
564
|
"table_properties" => [
|
507
565
|
{
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
566
|
+
"property" => "title",
|
567
|
+
"visible" => true,
|
568
|
+
"width" => 280,
|
569
|
+
},
|
512
570
|
{
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
571
|
+
"property" => "aliases",
|
572
|
+
"visible" => true,
|
573
|
+
"width" => 200,
|
574
|
+
},
|
517
575
|
{
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
576
|
+
"property" => "category",
|
577
|
+
"visible" => true,
|
578
|
+
"width" => 200,
|
579
|
+
},
|
522
580
|
{
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
581
|
+
"property" => "description",
|
582
|
+
"visible" => true,
|
583
|
+
"width" => 200,
|
584
|
+
},
|
527
585
|
{
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
586
|
+
"property" => "ios_version",
|
587
|
+
"visible" => true,
|
588
|
+
"width" => 200,
|
589
|
+
},
|
590
|
+
{
|
591
|
+
"property" => "tags",
|
592
|
+
"visible" => true,
|
593
|
+
"width" => 200,
|
594
|
+
},
|
532
595
|
{
|
533
|
-
"property" => "tags",
|
534
|
-
"visible" => true,
|
535
|
-
"width" => 200,
|
536
|
-
},
|
537
|
-
{
|
538
596
|
"property" => "phone",
|
539
597
|
"visible" => true,
|
540
598
|
"width" => 200,
|
541
599
|
},
|
542
600
|
{
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
601
|
+
"property" => "unicode_version",
|
602
|
+
"visible" => true,
|
603
|
+
"width" => 200,
|
604
|
+
},
|
547
605
|
],
|
548
606
|
}
|
549
607
|
{
|
@@ -563,11 +621,11 @@ module Utils
|
|
563
621
|
table = "block"
|
564
622
|
path = [
|
565
623
|
"properties",
|
566
|
-
column_name
|
624
|
+
column_name,
|
567
625
|
]
|
568
626
|
command = "set"
|
569
627
|
args = [[
|
570
|
-
new_value
|
628
|
+
new_value,
|
571
629
|
]]
|
572
630
|
|
573
631
|
{
|
@@ -575,11 +633,18 @@ module Utils
|
|
575
633
|
table: table,
|
576
634
|
path: path,
|
577
635
|
command: command,
|
578
|
-
args: args
|
636
|
+
args: args,
|
579
637
|
}
|
580
638
|
end
|
581
639
|
end
|
582
640
|
|
641
|
+
class SchemaTypeError < StandardError
|
642
|
+
def initialize(msg="Custom exception that is raised when an invalid property type is passed as a mapping.", exception_type="schema_type")
|
643
|
+
@exception_type = exception_type
|
644
|
+
super(msg)
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
583
648
|
def build_payload(operations, request_ids)
|
584
649
|
# ! properly formats the payload for Notions backend.
|
585
650
|
# ! operations -> an array of hashes that define the operations to perform : ``Array[Hash]``
|
@@ -600,4 +665,4 @@ module Utils
|
|
600
665
|
}
|
601
666
|
payload
|
602
667
|
end
|
603
|
-
end
|
668
|
+
end
|
data/lib/notion_api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: notion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Murphy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|