notion 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5a96adb5d26c56e00d6f8a370b5c272bb69ecd33c57b4db37a483c8ddb70dca
4
- data.tar.gz: ba367e26e35f4632a3fd25a2c9636b65eb14f602a06311715b4c80ec1a5154bf
3
+ metadata.gz: 4e1a5c0f54236d8842fa41dbe95b2ead841871473497529b0ab9c2a008554399
4
+ data.tar.gz: d25331c5b07238ec8cdd2f087d5763fe360822e81cbe39783f30bb857509980e
5
5
  SHA512:
6
- metadata.gz: 3d3f9703c7192ab1654b70b308973da70a9501a8b1d9500bbe310719b863aeade15afcf02acb041f701db657c59c41545ea1df0bff27798c6fca5860aff9fb8f
7
- data.tar.gz: 13df40b25461a064419604046677f15e14aad820c7064be1d41ca0590f527198f4708156bbf3e9c16149ec61f1e20c65f1c8f2ddc9d9fc175e0ef959a7537ea3
6
+ metadata.gz: fdcfcc8a0b2a93dcc0b12081d42bcbb3399adaf7972a81d6afc84ba45a26e0fd0caa36bd8c280c52157c698b5fe8d22c180f84f678571ca08be8552e16810999
7
+ data.tar.gz: 38a5230378e5c17be11e32c19fac25d1001131e0d41f423554ff2c81820e9287c46ced1f67ec5b22c565f9c93a3578cddadd8ec0332779758ca081367cf7437a
data/README.md CHANGED
@@ -37,6 +37,9 @@ The following attributes can be read from any block class instance:
37
37
  3. `parent_id`: the parent ID of the block.
38
38
  4. `type`: the type of the block.
39
39
 
40
+ To update the title of the page:
41
+ ![Update the title of a page](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/change_title.gif)
42
+
40
43
  ## Retrieving a Block within the Page
41
44
  Now that you have retrieved a Notion Page, you have full access to the blocks on that page. You can retrieve a specific block or collection view, retrieve all children IDs (array of children IDs), or retrieve all children (array of children class instances).
42
45
 
@@ -48,6 +51,7 @@ To retrieve a specific block, you can use the `get_block` method. This method ac
48
51
  #<TextBlock id="2cbbe0bf-34cd-409b-9162-64284b33e526" title="TEST" parent_id="d2ce338f-19e8-47f5-86bd-17679f490e66">
49
52
  ```
50
53
  Any Notion Block has access to the following methods:
54
+
51
55
  1. `title=` → change the title of a block.
52
56
  ```ruby
53
57
  >>> @block = @client.get_block("2cbbe0bf-34cd-409b-9162-64284b33e526")
@@ -57,6 +61,8 @@ Any Notion Block has access to the following methods:
57
61
  >>> @block.title
58
62
  "New Title Here"
59
63
  ```
64
+ For example:
65
+ ![Update the title of a block](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/change%20block%20title.gif)
60
66
  2. `convert` → convert a block to a different type.
61
67
  ```ruby
62
68
  >>> @block = @client.get_block("2cbbe0bf-34cd-409b-9162-64284b33e526")
@@ -68,12 +74,17 @@ Any Notion Block has access to the following methods:
68
74
  >>> @new_block # new class instance returned...
69
75
  #<NotionAPI::CalloutBlock:0x00007ffb75b19ea0 id="2cbbe0bf-34cd-409b-9162-64284b33e526" title="New Title Here" parent_id="d2ce338f-19e8-47f5-86bd-17679f490e66">
70
76
  ```
77
+ For example:
78
+ ![Convert a page](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/change%20to%20todo%2C%20check.gif)
79
+
71
80
  3. `duplicate`→ duplicate the current block.
72
81
  ```ruby
73
82
  >>> @block = @client.get_block("2cbbe0bf-34cd-409b-9162-64284b33e526")
74
83
  >>> @block.duplicate # block is duplicated and placed directly after the current block
75
84
  >>> @block.duplicate("f13da22b-9012-4c49-ac41-6b7f97bd519e") # the duplicated block is placed after 'f13da22b-9012-4c49-ac41-6b7f97bd519e'
76
85
  ```
86
+ For example:
87
+ ![Convert a page](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/duplicate.gif)
77
88
  4. `move` → move a block to another location.
78
89
  ```ruby
79
90
  >>> @block = @client.get_block("2cbbe0bf-34cd-409b-9162-64284b33e526")
@@ -81,6 +92,8 @@ Any Notion Block has access to the following methods:
81
92
  >>> @block.move(@target_block) # @block moved to **after** @target_block
82
93
  >>> @block.move(@target_block, "before") # @block moved to **before** @target_block
83
94
  ```
95
+ For example:
96
+ ![move a block](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/move_before_and_after.gif)
84
97
  ### Get a Collection View - Table
85
98
  To retrieve a collection, you use the `get_collection` method. This method is designed to work with Table collections, but the codebase is actively being updated to support others:
86
99
  ```ruby
@@ -110,6 +123,27 @@ ent.rb
110
123
  ```
111
124
 
112
125
  ## Creating New Blocks
126
+ Here's a high-level example:
127
+ ![create a callout a block](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/create.gif)
128
+ The block types available to the `create` method are:
129
+ 1. `DividerBlock`
130
+ 2. `TodoBlock`
131
+ 3. `CodeBlock`
132
+ 4. `HeaderBlock`
133
+ 5. `SubHeaderBlock`
134
+ 6. `SubSubHeaderBlock`
135
+ 7. `PageBlock`
136
+ 8. `ToggleBlock`
137
+ 9. `BulletedBlock`
138
+ 10. `NumberedBlock`
139
+ 11. `QuoteBlock`
140
+ 12. `CalloutBlock`
141
+ 13. `LatexBlock`
142
+ 14. `TextBlock`
143
+ 15. `ImageBlock` and
144
+ 16. `TableOfContentsBlock`.
145
+ If you want to create a collection, utilize the `create_collection` method [defined below].
146
+
113
147
  To create a new block, you have a few options:
114
148
  ### Create a block whose parent is the page
115
149
  If you want to create a new block whose parent ID is the **page**, call the `create` method on the PageBlock instance.
@@ -181,11 +215,14 @@ Let's say we have the following JSON data:
181
215
  }
182
216
  ]
183
217
  ```
184
- A new collection containing this data is created with the following code:
218
+ A new table collection view containing this data is created with the following code:
185
219
  ```ruby
186
220
  >>> @page = @client.get_page("https://www.notion.so/danmurphy/Notion-API-Testing-66447bc817f044bc81ed3cf4802e9b00")
187
221
  >>> @page.create_collection("table", "title for table", JSON.parse(File.read("./path/to/emoji_json_data.json")))
188
222
  ```
223
+ Here's an example with a larger dataset:
224
+ ![create a collection view table](https://github.com/danmurphy1217/notion-ruby/blob/master/gifs/create%20collection.gif)
225
+
189
226
  Additionally, say you already have a Table and want to add a new row with it containing the following data:
190
227
  ```ruby
191
228
  {
@@ -203,3 +240,10 @@ Additionally, say you already have a Table and want to add a new row with it con
203
240
  >>> @collection = @page.get_collection("f1664a99-165b-49cc-811c-84f37655908a")
204
241
  >>> @collection.add_row(JSON.parse(File.read("path/to/new_emoji_row.json")))
205
242
  ```
243
+
244
+ The first argument passed to `create_collection` determines which type of collection view to create. In the above example, a "table" is created, but other supported options are:
245
+ 1. list
246
+ 2. board
247
+ 3. calendar
248
+ 4. timeline
249
+ 5. gallery
@@ -1,986 +1,23 @@
1
- # frozen_string_literal: true
1
+ require_relative "notion_types/template"
2
+ require_relative "notion_types/bulleted_block"
3
+ require_relative "notion_types/callout_block"
4
+ require_relative "notion_types/code_block"
5
+ require_relative "notion_types/collection_view_blocks"
6
+ require_relative "notion_types/column_list_block"
7
+ require_relative "notion_types/divider_block"
8
+ require_relative "notion_types/quote_block"
9
+ require_relative "notion_types/page_block"
10
+ require_relative "notion_types/image_block"
11
+ require_relative "notion_types/latex_block"
12
+ require_relative "notion_types/numbered_block"
13
+ require_relative "notion_types/header_block"
14
+ require_relative "notion_types/sub_header_block"
15
+ require_relative "notion_types/sub_sub_header"
16
+ require_relative "notion_types/table_of_contents_block"
17
+ require_relative "notion_types/text_block"
18
+ require_relative "notion_types/todo_block"
19
+ require_relative "notion_types/toggle_block"
2
20
 
3
- require_relative 'core'
4
- require 'httparty'
5
-
6
- module NotionAPI
7
- # Base Template for all blocks. Inherits core methods from the Block class defined in block.rb
8
- class BlockTemplate < Core
9
- include Utils
10
-
11
- attr_reader :id, :title, :parent_id
12
-
13
- def initialize(id, title, parent_id)
14
- @id = id
15
- @title = title
16
- @parent_id = parent_id
17
- end
18
-
19
- def title=(new_title)
20
- # ! Change the title of a block.
21
- # ! new_title -> new title for the block : ``str``
22
- request_id = extract_id(SecureRandom.hex(16))
23
- transaction_id = extract_id(SecureRandom.hex(16))
24
- space_id = extract_id(SecureRandom.hex(16))
25
- update_title(new_title.to_s, request_id, transaction_id, space_id)
26
- @title = new_title
27
- end
28
-
29
- def convert(block_class_to_convert_to)
30
- # ! convert a block from its current type to another.
31
- # ! block_class_to_convert_to -> the type of block to convert to : ``cls``
32
- if type == block_class_to_convert_to.notion_type
33
- # if converting to same type, skip and return self
34
- self
35
- else
36
- # setup cookies, headers, and grab/create static vars for request
37
- cookies = Core.options['cookies']
38
- headers = Core.options['headers']
39
- request_url = URLS[:UPDATE_BLOCK]
40
-
41
- # set random IDs for request
42
- request_id = extract_id(SecureRandom.hex(16))
43
- transaction_id = extract_id(SecureRandom.hex(16))
44
- space_id = extract_id(SecureRandom.hex(16))
45
- request_ids = {
46
- request_id: request_id,
47
- transaction_id: transaction_id,
48
- space_id: space_id
49
- }
50
-
51
- # build hash's that contain the operations to send to Notions backend
52
- convert_type_hash = Utils::BlockComponents.convert_type(@id, block_class_to_convert_to)
53
- last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(@parent_id)
54
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
55
-
56
- operations = [
57
- convert_type_hash,
58
- last_edited_time_parent_hash,
59
- last_edited_time_child_hash
60
- ]
61
-
62
- request_body = build_payload(operations, request_ids)
63
- response = HTTParty.post(
64
- request_url,
65
- body: request_body.to_json,
66
- cookies: cookies,
67
- headers: headers
68
- )
69
- 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}.
70
- Please try again, and if issues persist open an issue in GitHub."; end
71
-
72
- block_class_to_convert_to.new(@id, @title, @parent_id)
73
-
74
- end
75
- end
76
-
77
- def duplicate(target_block = nil)
78
- # ! duplicate the block that this method is invoked upon.
79
- # ! target_block -> the block to place the duplicated block after. Can be any valid Block ID! : ``str``
80
- cookies = Core.options['cookies']
81
- headers = Core.options['headers']
82
- request_url = URLS[:UPDATE_BLOCK]
83
-
84
- new_block_id = extract_id(SecureRandom.hex(16))
85
- request_id = extract_id(SecureRandom.hex(16))
86
- transaction_id = extract_id(SecureRandom.hex(16))
87
- space_id = extract_id(SecureRandom.hex(16))
88
-
89
- root_children = children_ids(@id)
90
- sub_children = []
91
- root_children.each { |root_id| sub_children.push(children_ids(root_id)) }
92
-
93
- request_ids = {
94
- request_id: request_id,
95
- transaction_id: transaction_id,
96
- space_id: space_id
97
- }
98
- body = {
99
- pageId: @id,
100
- chunkNumber: 0,
101
- limit: 100,
102
- verticalColumns: false
103
- }
104
-
105
- user_notion_id = get_notion_id(body)
106
-
107
- block = target_block ? get(target_block) : self # allows dev to place block anywhere!
108
-
109
- duplicate_hash = Utils::BlockComponents.duplicate(type, @title, block.id, new_block_id, user_notion_id, root_children)
110
- set_parent_alive_hash = Utils::BlockComponents.set_parent_to_alive(block.parent_id, new_block_id)
111
- block_location_hash = Utils::BlockComponents.block_location_add(block.parent_id, block.id, new_block_id, target_block, 'listAfter')
112
- last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(block.parent_id)
113
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(block.id)
114
-
115
- operations = [
116
- duplicate_hash,
117
- set_parent_alive_hash,
118
- block_location_hash,
119
- last_edited_time_parent_hash,
120
- last_edited_time_child_hash
121
- ]
122
-
123
- request_body = build_payload(operations, request_ids)
124
- response = HTTParty.post(
125
- request_url,
126
- body: request_body.to_json,
127
- cookies: cookies,
128
- headers: headers
129
- )
130
- 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}.
131
- Please try again, and if issues persist open an issue in GitHub."; end
132
-
133
- class_to_return = NotionAPI.const_get(Classes.select { |cls| NotionAPI.const_get(cls).notion_type == type }.join.to_s)
134
- class_to_return.new(new_block_id, @title, block.parent_id)
135
- end
136
-
137
- def move(target_block, position = 'after')
138
- # ! move the block to a new location.
139
- # ! target_block -> the targetted block to move to. : ``str``
140
- # ! position -> where the block should be listed, in positions relative to the target_block [before, after, top-child, last-child]
141
- positions_hash = {
142
- 'after' => 'listAfter',
143
- 'before' => 'listBefore'
144
- }
145
-
146
- unless positions_hash.keys.include?(position); raise ArgumentError, "Invalid position. You said: #{position}, valid options are: #{positions_hash.keys.join(', ')}"; end
147
-
148
- position_command = positions_hash[position]
149
- cookies = Core.options['cookies']
150
- headers = Core.options['headers']
151
- request_url = URLS[:UPDATE_BLOCK]
152
-
153
- request_id = extract_id(SecureRandom.hex(16))
154
- transaction_id = extract_id(SecureRandom.hex(16))
155
- space_id = extract_id(SecureRandom.hex(16))
156
-
157
- request_ids = {
158
- request_id: request_id,
159
- transaction_id: transaction_id,
160
- space_id: space_id
161
- }
162
-
163
- check_parents = (@parent_id == target_block.parent_id)
164
- set_block_dead_hash = Utils::BlockComponents.set_block_to_dead(@id) # kill the block this method is invoked on...
165
- block_location_remove_hash = Utils::BlockComponents.block_location_remove(@parent_id, @id) # remove the block this method is invoked on...
166
- parent_location_hash = Utils::BlockComponents.parent_location_add(check_parents ? @parent_id : target_block.parent_id, @id) # set parent location to alive
167
- block_location_add_hash = Utils::BlockComponents.block_location_add(check_parents ? @parent_id : target_block.parent_id, @id, target_block.id, position_command)
168
- last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(@parent_id)
169
-
170
- if check_parents
171
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
172
- operations = [
173
- set_block_dead_hash,
174
- block_location_remove_hash,
175
- parent_location_hash,
176
- block_location_add_hash,
177
- last_edited_time_parent_hash,
178
- last_edited_time_child_hash
179
- ]
180
- else
181
- last_edited_time_new_parent_hash = Utils::BlockComponents.last_edited_time(target_block.parent_id)
182
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
183
- @parent_id = target_block.parent_id
184
- operations = [
185
- set_block_dead_hash,
186
- block_location_remove_hash,
187
- parent_location_hash,
188
- block_location_add_hash,
189
- last_edited_time_parent_hash,
190
- last_edited_time_new_parent_hash,
191
- last_edited_time_child_hash
192
- ]
193
- end
194
- request_body = build_payload(operations, request_ids)
195
- response = HTTParty.post(
196
- request_url,
197
- body: request_body.to_json,
198
- cookies: cookies,
199
- headers: headers
200
- )
201
- 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}.
202
- Please try again, and if issues persist open an issue in GitHub."; end
203
-
204
- self
205
- end
206
-
207
- def create(block_type, block_title, target = nil, position = 'after')
208
- # ! create a new block
209
- # ! block_type -> the type of block to create : ``cls``
210
- # ! block_title -> the title of the new block : ``str``
211
- # ! target -> the block_id that the new block should be placed after. ``str``
212
- # ! position -> 'after' or 'before'
213
- positions_hash = {
214
- 'after' => 'listAfter',
215
- 'before' => 'listBefore'
216
- }
217
- unless positions_hash.keys.include?(position); raise "Invalid position. You said: #{position}, valid options are: #{positions_hash.keys.join(', ')}"; end
218
-
219
- position_command = positions_hash[position]
220
-
221
- cookies = Core.options['cookies']
222
- headers = Core.options['headers']
223
-
224
- new_block_id = extract_id(SecureRandom.hex(16))
225
- request_id = extract_id(SecureRandom.hex(16))
226
- transaction_id = extract_id(SecureRandom.hex(16))
227
- space_id = extract_id(SecureRandom.hex(16))
228
-
229
- request_ids = {
230
- request_id: request_id,
231
- transaction_id: transaction_id,
232
- space_id: space_id
233
- }
234
-
235
- create_hash = Utils::BlockComponents.create(new_block_id, block_type.notion_type)
236
- set_parent_alive_hash = Utils::BlockComponents.set_parent_to_alive(@id, new_block_id)
237
- block_location_hash = Utils::BlockComponents.block_location_add(@id, @id, new_block_id, target, position_command)
238
- last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(@id)
239
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
240
- title_hash = Utils::BlockComponents.title(new_block_id, block_title)
241
-
242
- operations = [
243
- create_hash,
244
- set_parent_alive_hash,
245
- block_location_hash,
246
- last_edited_time_parent_hash,
247
- last_edited_time_child_hash,
248
- title_hash
249
- ]
250
-
251
- request_url = URLS[:UPDATE_BLOCK]
252
- request_body = build_payload(operations, request_ids)
253
- response = HTTParty.post(
254
- request_url,
255
- body: request_body.to_json,
256
- cookies: cookies,
257
- headers: headers
258
- )
259
- 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}.
260
- Please try again, and if issues persist open an issue in GitHub."; end
261
-
262
- block_type.new(new_block_id, block_title, @id)
263
- end
264
-
265
- private
266
-
267
- def get(url_or_id)
268
- # ! retrieve a Notion Block and return its instantiated class object.
269
- # ! url_or_id -> the block ID or URL : ``str``
270
- clean_id = extract_id(url_or_id)
271
-
272
- request_body = {
273
- pageId: clean_id,
274
- chunkNumber: 0,
275
- limit: 100,
276
- verticalColumns: false
277
- }
278
- jsonified_record_response = get_all_block_info(clean_id, request_body)
279
- i = 0
280
- while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
281
- return {} if i >= 10
282
-
283
- jsonified_record_response = get_all_block_info(clean_id, request_body)
284
- i += 1
285
- end
286
- block_type = extract_type(clean_id, jsonified_record_response)
287
- block_parent_id = extract_parent_id(clean_id, jsonified_record_response)
288
-
289
- if block_type.nil?
290
- {}
291
- else
292
- block_class = NotionAPI.const_get(BLOCK_TYPES[block_type].to_s)
293
- if block_class == NotionAPI::CollectionView
294
- block_collection_id = extract_collection_id(clean_id, jsonified_record_response)
295
- block_view_id = extract_view_ids(clean_id, jsonified_record_response)
296
- collection_title = extract_collection_title(clean_id, block_collection_id, jsonified_record_response)
297
- block_class.new(clean_id, collection_title, block_parent_id, block_collection_id, block_view_id.join)
298
- else
299
- block_title = extract_title(clean_id, jsonified_record_response)
300
- block_class.new(clean_id, block_title, block_parent_id)
301
- end
302
- end
303
- end
304
-
305
- def update_title(new_title, request_id, transaction_id, space_id)
306
- # ! Helper method for sending POST request to change title of block.
307
- # ! new_title -> new title for the block : ``str``
308
- # ! request_id -> the unique ID for the request key. Generated using SecureRandom : ``str``
309
- # ! transaction_id -> the unique ID for the transaction key. Generated using SecureRandom: ``str``
310
- # ! transaction_id -> the unique ID for the space key. Generated using SecureRandom: ``str``
311
- # setup cookies, headers, and grab/create static vars for request
312
- cookies = Core.options['cookies']
313
- headers = Core.options['headers']
314
- request_url = URLS[:UPDATE_BLOCK]
315
-
316
- # set unique IDs for request
317
- request_ids = {
318
- request_id: request_id,
319
- transaction_id: transaction_id,
320
- space_id: space_id
321
- }
322
-
323
- # build and set operations to send to Notion
324
- title_hash = Utils::BlockComponents.title(@id, new_title)
325
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
326
- operations = [
327
- title_hash,
328
- last_edited_time_child_hash
329
- ]
330
-
331
- request_body = build_payload(operations, request_ids) # defined in utils.rb
332
-
333
- response = HTTParty.post(
334
- request_url,
335
- body: request_body.to_json,
336
- cookies: cookies,
337
- headers: headers
338
- )
339
- response.body
340
- end
341
- end
342
-
343
- # divider block: ---------
344
- class DividerBlock < BlockTemplate
345
- @notion_type = 'divider'
346
- @type = 'divider'
347
-
348
- def type
349
- NotionAPI::DividerBlock.notion_type
350
- end
351
-
352
- class << self
353
- attr_reader :notion_type, :type
354
- end
355
- end
356
-
357
- # To-Do block: best for checklists and tracking to-dos.
358
- class TodoBlock < BlockTemplate
359
- @notion_type = 'to_do'
360
- @type = 'to_do'
361
-
362
- def type
363
- NotionAPI::TodoBlock.notion_type
364
- end
365
-
366
- class << self
367
- attr_reader :notion_type, :type
368
- end
369
-
370
- def checked=(checked_value)
371
- # ! change the checked property of the Todo Block.
372
- # ! checked_value -> boolean value used to determine whether the block should be checked [yes] or not [no] : ``str``
373
- # set static variables for request
374
- cookies = Core.options['cookies']
375
- headers = Core.options['headers']
376
- request_url = URLS[:UPDATE_BLOCK]
377
-
378
- # set unique values for request
379
- request_id = extract_id(SecureRandom.hex(16))
380
- transaction_id = extract_id(SecureRandom.hex(16))
381
- space_id = extract_id(SecureRandom.hex(16))
382
- request_ids = {
383
- request_id: request_id,
384
- transaction_id: transaction_id,
385
- space_id: space_id
386
- }
387
-
388
- if %w[yes no].include?(checked_value.downcase)
389
- checked_hash = Utils::BlockComponents.checked_todo(@id, checked_value.downcase)
390
- last_edited_time_parent_hash = Utils::BlockComponents.last_edited_time(@parent_id)
391
- last_edited_time_child_hash = Utils::BlockComponents.last_edited_time(@id)
392
-
393
- operations = [
394
- checked_hash,
395
- last_edited_time_parent_hash,
396
- last_edited_time_child_hash
397
- ]
398
- request_body = build_payload(operations, request_ids)
399
- response = HTTParty.post(
400
- request_url,
401
- body: request_body.to_json,
402
- cookies: cookies,
403
- headers: headers
404
- )
405
- 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}.
406
- Please try again, and if issues persist open an issue in GitHub."; end
407
-
408
- true
409
- else
410
- false
411
- end
412
- end
413
- end
414
-
415
- # Code block: used to store code, should be assigned a coding language.
416
- class CodeBlock < BlockTemplate
417
- @notion_type = 'code'
418
- @type = 'code'
419
-
420
- def type
421
- NotionAPI::CodeBlock.notion_type
422
- end
423
-
424
- class << self
425
- attr_reader :notion_type, :type
426
- end
427
- end
428
-
429
- # Header block: H1
430
- class HeaderBlock < BlockTemplate
431
- @notion_type = 'header'
432
- @type = 'header'
433
-
434
- def type
435
- NotionAPI::HeaderBlock.notion_type
436
- end
437
-
438
- class << self
439
- attr_reader :notion_type, :type
440
- end
441
- end
442
-
443
- # SubHeader Block: H2
444
- class SubHeaderBlock < BlockTemplate
445
- @notion_type = 'sub_header'
446
- @type = 'sub_header'
447
-
448
- def type
449
- NotionAPI::SubHeaderBlock.notion_type
450
- end
451
-
452
- class << self
453
- attr_reader :notion_type, :type
454
- end
455
- end
456
-
457
- # Sub-Sub Header Block: H3
458
- class SubSubHeaderBlock < BlockTemplate
459
- @notion_type = 'sub_sub_header'
460
- @type = 'sub_sub_header'
461
-
462
- def type
463
- NotionAPI::SubSubHeaderBlock.notion_type
464
- end
465
-
466
- class << self
467
- attr_reader :notion_type, :type
468
- end
469
- end
470
-
471
- # Page Block, entrypoint for the application
472
- class PageBlock < BlockTemplate
473
- @notion_type = 'page'
474
- @type = 'page'
475
-
476
- def type
477
- NotionAPI::PageBlock.notion_type
478
- end
479
-
480
- class << self
481
- attr_reader :notion_type, :type
482
- end
483
-
484
- def get_block(url_or_id)
485
- # ! retrieve a Notion Block and return its instantiated class object.
486
- # ! url_or_id -> the block ID or URL : ``str``
487
- get(url_or_id)
488
- end
489
-
490
- def get_collection(url_or_id)
491
- # ! retrieve a Notion Collection and return its instantiated class object.
492
- # ! url_or_id -> the block ID or URL : ``str``
493
- clean_id = extract_id(url_or_id)
494
-
495
- request_body = {
496
- pageId: clean_id,
497
- chunkNumber: 0,
498
- limit: 100,
499
- verticalColumns: false
500
- }
501
- jsonified_record_response = get_all_block_info(clean_id, request_body)
502
- i = 0
503
- while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
504
- return {} if i >= 10
505
-
506
- jsonified_record_response = get_all_block_info(clean_id, request_body)
507
- i += 1
508
- end
509
- block_parent_id = extract_parent_id(clean_id, jsonified_record_response)
510
- block_collection_id = extract_collection_id(clean_id, jsonified_record_response)
511
- block_view_id = extract_view_ids(clean_id, jsonified_record_response).join
512
- block_title = extract_collection_title(clean_id, block_collection_id, jsonified_record_response)
513
-
514
- CollectionView.new(clean_id, block_title, block_parent_id, block_collection_id, block_view_id)
515
- end
516
-
517
- def create_collection(collection_type, collection_title, data)
518
- # ! create a Notion Collection View and return its instantiated class object.
519
- # ! _collection_type -> the type of collection to create : ``str``
520
- # ! collection_title -> the title of the collection view : ``str``
521
- # ! data -> JSON data to add to the table : ``str``
522
-
523
- valid_types = %w[table board list timeline calendar gallery]
524
- unless valid_types.include?(collection_type) ; raise ArgumentError, "That collection type is not yet supported. Try: #{valid_types.join}."; end
525
- cookies = Core.options['cookies']
526
- headers = Core.options['headers']
527
-
528
- new_block_id = extract_id(SecureRandom.hex(16))
529
- parent_id = extract_id(SecureRandom.hex(16))
530
- collection_id = extract_id(SecureRandom.hex(16))
531
- view_id = extract_id(SecureRandom.hex(16))
532
-
533
- children = []
534
- alive_blocks = []
535
- data.each do |_row|
536
- child = extract_id(SecureRandom.hex(16))
537
- children.push(child)
538
- alive_blocks.push(Utils::CollectionViewComponents.set_collection_blocks_alive(child, collection_id))
539
- end
540
-
541
- request_id = extract_id(SecureRandom.hex(16))
542
- transaction_id = extract_id(SecureRandom.hex(16))
543
- space_id = extract_id(SecureRandom.hex(16))
544
-
545
- request_ids = {
546
- request_id: request_id,
547
- transaction_id: transaction_id,
548
- space_id: space_id
549
- }
550
-
551
- create_collection_view = Utils::CollectionViewComponents.create_collection_view(new_block_id, collection_id, view_id)
552
- configure_view = Utils::CollectionViewComponents.set_view_config(collection_type, new_block_id, view_id, children)
553
-
554
- # returns the JSON and some useful column mappings...
555
- column_data = Utils::CollectionViewComponents.set_collection_columns(collection_id, new_block_id, data)
556
- configure_columns_hash = column_data[0]
557
- column_mappings = column_data[1]
558
- set_parent_alive_hash = Utils::BlockComponents.set_parent_to_alive(@id, new_block_id)
559
- add_block_hash = Utils::BlockComponents.block_location_add(@id, @id, new_block_id, nil, 'listAfter')
560
- new_block_edited_time = Utils::BlockComponents.last_edited_time(new_block_id)
561
- collection_title_hash = Utils::CollectionViewComponents.set_collection_title(collection_title, collection_id)
562
-
563
- operations = [
564
- create_collection_view,
565
- configure_view,
566
- configure_columns_hash,
567
- set_parent_alive_hash,
568
- add_block_hash,
569
- new_block_edited_time,
570
- collection_title_hash
571
- ]
572
- operations << alive_blocks
573
- all_ops = operations.flatten
574
- data.each_with_index do |row, i|
575
- child = children[i]
576
- row.keys.each_with_index do |col_name, j|
577
- child_component = Utils::CollectionViewComponents.insert_data(child, j.zero? ? 'title' : col_name, row[col_name], column_mappings[j])
578
- all_ops.push(child_component)
579
- end
580
- end
581
-
582
- request_url = URLS[:UPDATE_BLOCK]
583
- request_body = build_payload(all_ops, request_ids)
584
- response = HTTParty.post(
585
- request_url,
586
- body: request_body.to_json,
587
- cookies: cookies,
588
- headers: headers
589
- )
590
-
591
- 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}.
592
- Please try again, and if issues persist open an issue in GitHub."; end
593
-
594
- CollectionView.new(new_block_id, collection_title, parent_id, collection_id, view_id)
595
- end
596
- end
597
-
598
- # Toggle block: best for storing children blocks
599
- class ToggleBlock < BlockTemplate
600
- @notion_type = 'toggle'
601
- @type = 'toggle'
602
-
603
- def type
604
- NotionAPI::ToggleBlock.notion_type
605
- end
606
-
607
- class << self
608
- attr_reader :notion_type, :type
609
- end
610
- end
611
-
612
- # Bullet list block: best for an unordered list
613
- class BulletedBlock < BlockTemplate
614
- @notion_type = 'bulleted_list'
615
- @type = 'bulleted_list'
616
-
617
- def type
618
- NotionAPI::BulletedBlock.notion_type
619
- end
620
-
621
- class << self
622
- attr_reader :notion_type, :type
623
- end
624
- end
625
-
626
- # Numbered list Block: best for an ordered list
627
- class NumberedBlock < BlockTemplate
628
- @notion_type = 'numbered_list'
629
- @type = 'numbered_list'
630
-
631
- def type
632
- NotionAPI::NumberedBlock.notion_type
633
- end
634
-
635
- class << self
636
- attr_reader :notion_type, :type
637
- end
638
- end
639
-
640
- # best for memorable information
641
- class QuoteBlock < BlockTemplate
642
- @notion_type = 'quote'
643
- @type = 'quote'
644
-
645
- def type
646
- NotionAPI::QuoteBlock.notion_type
647
- end
648
-
649
- class << self
650
- attr_reader :notion_type, :type
651
- end
652
- end
653
-
654
- # same as quote... works similarly to page block
655
- class CalloutBlock < BlockTemplate
656
- @notion_type = 'callout'
657
- @type = 'callout'
658
-
659
- def type
660
- NotionAPI::CalloutBlock.notion_type
661
- end
662
-
663
- class << self
664
- attr_reader :notion_type, :type
665
- end
666
- end
667
-
668
- # simiilar to code block but for mathematical functions.
669
- class LatexBlock < BlockTemplate
670
- @notion_type = 'equation'
671
- @type = 'equation'
672
-
673
- def type
674
- NotionAPI::LatexBlock.notion_type
675
- end
676
-
677
- class << self
678
- attr_reader :notion_type, :type
679
- end
680
- end
681
-
682
- # good for just about anything (-:
683
- class TextBlock < BlockTemplate
684
- @notion_type = 'text'
685
- @type = 'text'
686
-
687
- def type
688
- NotionAPI::TextBlock.notion_type
689
- end
690
-
691
- class << self
692
- attr_reader :notion_type, :type
693
- end
694
- end
695
-
696
- # good for visual information
697
- class ImageBlock < BlockTemplate
698
- @notion_type = 'image'
699
- @type = 'image'
700
-
701
- def type
702
- NotionAPI::ImageBlock.notion_type
703
- end
704
-
705
- class << self
706
- attr_reader :notion_type, :type
707
- end
708
- end
709
-
710
- # maps out the headers - sub-headers - sub-sub-headers on the page
711
- class TableOfContentsBlock < BlockTemplate
712
- @notion_type = 'table_of_contents'
713
- @type = 'table_of_contents'
714
-
715
- def type
716
- NotionAPI::TableOfContentsBlock.notion_type
717
- end
718
-
719
- class << self
720
- attr_reader :notion_type, :type
721
- end
722
- end
723
-
724
- # no use case for this yet.
725
- class ColumnListBlock < BlockTemplate
726
- @notion_type = 'column_list'
727
- @type = 'column_list'
728
-
729
- def type
730
- NotionAPI::ColumnListBlock.notion_type
731
- end
732
-
733
- class << self
734
- attr_reader :notion_type, :type
735
- end
736
- end
737
-
738
- # no use case for this yet.
739
- class ColumnBlock < BlockTemplate
740
- @notion_type = 'column'
741
- @type = 'column'
742
-
743
- def type
744
- NotionAPI::ColumnBlock.notion_type
745
- end
746
-
747
- class << self
748
- attr_reader :notion_type, :type
749
- end
750
- end
751
- end
752
-
753
- module NotionAPI
754
- # collection views such as tables and timelines.
755
- class CollectionView < Core
756
- attr_reader :id, :title, :parent_id, :collection_id, :view_id
757
-
758
- @notion_type = 'collection_view'
759
- @type = 'collection_view'
760
-
761
- def type
762
- NotionAPI::CollectionView.notion_type
763
- end
764
-
765
- class << self
766
- attr_reader :notion_type, :type
767
- end
768
-
769
- def initialize(id, title, parent_id, collection_id, view_id)
770
- @id = id
771
- @title = title
772
- @parent_id = parent_id
773
- @collection_id = collection_id
774
- @view_id = view_id
775
- end
776
-
777
- def add_row(data)
778
- # ! add new row to Collection View table.
779
- # ! data -> data to add to table : ``hash``
780
-
781
- cookies = Core.options['cookies']
782
- headers = Core.options['headers']
783
-
784
- request_id = extract_id(SecureRandom.hex(16))
785
- transaction_id = extract_id(SecureRandom.hex(16))
786
- space_id = extract_id(SecureRandom.hex(16))
787
- new_block_id = extract_id(SecureRandom.hex(16))
788
- schema = extract_collection_schema(@collection_id, @view_id)
789
- keys = schema.keys
790
- col_map = {}
791
- keys.map { |key| col_map[schema[key]['name']] = key }
792
-
793
- request_ids = {
794
- request_id: request_id,
795
- transaction_id: transaction_id,
796
- space_id: space_id
797
- }
798
-
799
- instantiate_row = Utils::CollectionViewComponents.add_new_row(new_block_id)
800
- set_block_alive = Utils::CollectionViewComponents.set_collection_blocks_alive(new_block_id, @collection_id)
801
- new_block_edited_time = Utils::BlockComponents.last_edited_time(new_block_id)
802
- parent_edited_time = Utils::BlockComponents.last_edited_time(@parent_id)
803
-
804
- operations = [
805
- instantiate_row,
806
- set_block_alive,
807
- new_block_edited_time,
808
- parent_edited_time
809
- ]
810
-
811
- data.keys.each_with_index do |col_name, j|
812
- child_component = Utils::CollectionViewComponents.insert_data(new_block_id, j.zero? ? 'title' : col_map[col_name], data[col_name], j.zero? ? schema['title']["type"] : schema[col_map[col_name]]['type'])
813
- operations.push(child_component)
814
- end
815
-
816
- request_url = URLS[:UPDATE_BLOCK]
817
- request_body = build_payload(operations, request_ids)
818
- response = HTTParty.post(
819
- request_url,
820
- body: request_body.to_json,
821
- cookies: cookies,
822
- headers: headers
823
- )
824
-
825
- 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}.
826
- Please try again, and if issues persist open an issue in GitHub."; end
827
-
828
- NotionAPI::CollectionViewRow.new(new_block_id, @parent_id, @collection_id, @view_id)
829
- end
830
-
831
- def add_property(name, type)
832
- # ! add a property (column) to the table.
833
- # ! name -> name of the property : ``str``
834
- # ! type -> type of the property : ``str``
835
- cookies = Core.options['cookies']
836
- headers = Core.options['headers']
837
-
838
- request_id = extract_id(SecureRandom.hex(16))
839
- transaction_id = extract_id(SecureRandom.hex(16))
840
- space_id = extract_id(SecureRandom.hex(16))
841
-
842
- request_ids = {
843
- request_id: request_id,
844
- transaction_id: transaction_id,
845
- space_id: space_id
846
- }
847
-
848
- # create updated schema
849
- schema = extract_collection_schema(@collection_id, @view_id)
850
- schema[name] = {
851
- name: name,
852
- type: type
853
- }
854
- new_schema = {
855
- schema: schema
856
- }
857
-
858
- add_collection_property = Utils::CollectionViewComponents.add_collection_property(@collection_id, new_schema)
859
-
860
- operations = [
861
- add_collection_property
862
- ]
863
-
864
- request_url = URLS[:UPDATE_BLOCK]
865
- request_body = build_payload(operations, request_ids)
866
- response = HTTParty.post(
867
- request_url,
868
- body: request_body.to_json,
869
- cookies: cookies,
870
- headers: headers
871
- )
872
- 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}.
873
- Please try again, and if issues persist open an issue in GitHub."; end
874
-
875
- true
876
- end
877
-
878
- def row(row_id)
879
- # ! retrieve a row from a CollectionView Table.
880
- # ! row_id -> the ID for the row to retrieve: ``str``
881
- clean_id = extract_id(row_id)
882
-
883
- request_body = {
884
- pageId: clean_id,
885
- chunkNumber: 0,
886
- limit: 100,
887
- verticalColumns: false
888
- }
889
- jsonified_record_response = get_all_block_info(clean_id, request_body)
890
- schema = extract_collection_schema(@collection_id, @view_id)
891
- keys = schema.keys
892
- column_names = keys.map { |key| schema[key]['name'] }
893
- i = 0
894
- while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
895
- return {} if i >= 10
896
-
897
- jsonified_record_response = get_all_block_info(clean_id, request_body)
898
- i += 1
899
- end
900
- row_jsonified_response = jsonified_record_response['block'][clean_id]['value']['properties']
901
- row_data = {}
902
- keys.each_with_index { |key, idx| row_data[column_names[idx]] = row_jsonified_response[key] ? row_jsonified_response[key].flatten : [] }
903
- row_data
904
- end
905
-
906
- def row_ids
907
- # ! retrieve all Collection View table rows.
908
- clean_id = extract_id(@id)
909
-
910
- request_body = {
911
- pageId: clean_id,
912
- chunkNumber: 0,
913
- limit: 100,
914
- verticalColumns: false
915
- }
916
-
917
- jsonified_record_response = get_all_block_info(clean_id, request_body)
918
- i = 0
919
- while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
920
- return {} if i >= 10
921
-
922
- jsonified_record_response = get_all_block_info(clean_id, request_body)
923
- i += 1
924
- end
925
-
926
- jsonified_record_response['collection_view'][@view_id]['value']['page_sort']
927
- end
928
-
929
- def rows
930
- # ! returns all rows as instantiated class instances.
931
- row_id_array = row_ids
932
- parent_id = @parent_id
933
- collection_id = @collection_id
934
- view_id = @view_id
935
-
936
- row_id_array.map { |row_id| NotionAPI::CollectionViewRow.new(row_id, parent_id, collection_id, view_id) }
937
- end
938
-
939
- private
940
-
941
- def extract_collection_schema(collection_id, view_id)
942
- # ! retrieve the collection scehma. Useful for 'building' the backbone for a table.
943
- # ! collection_id -> the collection ID : ``str``
944
- # ! view_id -> the view ID : ``str``
945
- cookies = Core.options['cookies']
946
- headers = Core.options['headers']
947
-
948
- query_collection_hash = Utils::CollectionViewComponents.query_collection(collection_id, view_id, '')
949
-
950
- request_url = URLS[:GET_COLLECTION]
951
- response = HTTParty.post(
952
- request_url,
953
- body: query_collection_hash.to_json,
954
- cookies: cookies,
955
- headers: headers
956
- )
957
- response['recordMap']['collection'][collection_id]['value']['schema']
958
- end
959
- end
960
- # Class for each row in a Collection View Table.
961
- class CollectionViewRow < Core
962
- @notion_type = 'table_row'
963
- @type = 'table_row'
964
-
965
- def type
966
- NotionAPI::CollectionViewRow.notion_type
967
- end
968
-
969
- class << self
970
- attr_reader :notion_type, :type, :parent_id
971
- end
972
-
973
- attr_reader :parent_id, :id
974
- def initialize(id, parent_id, collection_id, view_id)
975
- @id = id
976
- @parent_id = parent_id
977
- @collection_id = collection_id
978
- @view_id = view_id
979
- end
980
- end
981
- end
982
-
983
- # gather a list of all the classes defined here...
984
21
  Classes = NotionAPI.constants.select { |c| NotionAPI.const_get(c).is_a? Class and c.to_s != 'BlockTemplate' and c.to_s != 'Core' and c.to_s !='Client' }
985
22
  notion_types = []
986
23
  Classes.each { |cls| notion_types.push(NotionAPI.const_get(cls).notion_type) }