notion 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -113,6 +113,29 @@ module NotionAPI
113
113
  children_ids(url_or_id).empty? ? [] : children_ids(url_or_id)[-1]
114
114
  end
115
115
 
116
+ def get_block_props_and_format(clean_id, block_title)
117
+ request_body = {
118
+ pageId: clean_id,
119
+ chunkNumber: 0,
120
+ limit: 100,
121
+ verticalColumns: false
122
+ }
123
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
124
+ i = 0
125
+ while jsonified_record_response.empty?
126
+ return {:properties => {title: [[block_title]]}, :format => {}} if i >= 10
127
+
128
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
129
+ i += 1
130
+ end
131
+ properties = jsonified_record_response['block'][clean_id]['value']['properties']
132
+ formats = jsonified_record_response['block'][clean_id]['value']['format']
133
+ return {
134
+ :properties => properties,
135
+ :format => formats
136
+ }
137
+ end
138
+
116
139
  def get_all_block_info(_clean_id, body)
117
140
  # ! retrieves all info pertaining to a block Id.
118
141
  # ! clean_id -> the block ID or URL cleaned : ``str``
@@ -193,7 +216,7 @@ module NotionAPI
193
216
  def extract_view_ids(clean_id, jsonified_record_response)
194
217
  jsonified_record_response['block'][clean_id]['value']['view_ids'] || []
195
218
  end
196
-
219
+
197
220
  def extract_id(url_or_id)
198
221
  # ! parse and clean the URL or ID object provided.
199
222
  # ! url_or_id -> the block ID or URL : ``str``
@@ -0,0 +1,17 @@
1
+ require_relative "template"
2
+
3
+ module NotionAPI
4
+ # Bullet list block: best for an unordered list
5
+ class BulletedBlock < BlockTemplate
6
+ @notion_type = "bulleted_list"
7
+ @type = "bulleted_list"
8
+
9
+ def type
10
+ NotionAPI::BulletedBlock.notion_type
11
+ end
12
+
13
+ class << self
14
+ attr_reader :notion_type, :type
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # same as quote... works similarly to page block
4
+ class CalloutBlock < BlockTemplate
5
+ @notion_type = 'callout'
6
+ @type = 'callout'
7
+
8
+ def type
9
+ NotionAPI::CalloutBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # Code block: used to store code, should be assigned a coding language.
4
+ class CodeBlock < BlockTemplate
5
+ @notion_type = 'code'
6
+ @type = 'code'
7
+
8
+ def type
9
+ NotionAPI::CodeBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,228 @@
1
+ module NotionAPI
2
+ # collection views such as tables and timelines.
3
+ class CollectionView < Core
4
+ attr_reader :id, :title, :parent_id, :collection_id, :view_id
5
+
6
+ @notion_type = 'collection_view'
7
+ @type = 'collection_view'
8
+
9
+ def type
10
+ NotionAPI::CollectionView.notion_type
11
+ end
12
+
13
+ class << self
14
+ attr_reader :notion_type, :type
15
+ end
16
+
17
+ def initialize(id, title, parent_id, collection_id, view_id)
18
+ @id = id
19
+ @title = title
20
+ @parent_id = parent_id
21
+ @collection_id = collection_id
22
+ @view_id = view_id
23
+ end
24
+
25
+ def add_row(data)
26
+ # ! add new row to Collection View table.
27
+ # ! data -> data to add to table : ``hash``
28
+
29
+ cookies = Core.options['cookies']
30
+ headers = Core.options['headers']
31
+
32
+ request_id = extract_id(SecureRandom.hex(16))
33
+ transaction_id = extract_id(SecureRandom.hex(16))
34
+ space_id = extract_id(SecureRandom.hex(16))
35
+ new_block_id = extract_id(SecureRandom.hex(16))
36
+ schema = extract_collection_schema(@collection_id, @view_id)
37
+ keys = schema.keys
38
+ col_map = {}
39
+ keys.map { |key| col_map[schema[key]['name']] = key }
40
+
41
+ request_ids = {
42
+ request_id: request_id,
43
+ transaction_id: transaction_id,
44
+ space_id: space_id
45
+ }
46
+
47
+ instantiate_row = Utils::CollectionViewComponents.add_new_row(new_block_id)
48
+ set_block_alive = Utils::CollectionViewComponents.set_collection_blocks_alive(new_block_id, @collection_id)
49
+ new_block_edited_time = Utils::BlockComponents.last_edited_time(new_block_id)
50
+ parent_edited_time = Utils::BlockComponents.last_edited_time(@parent_id)
51
+
52
+ operations = [
53
+ instantiate_row,
54
+ set_block_alive,
55
+ new_block_edited_time,
56
+ parent_edited_time
57
+ ]
58
+
59
+ data.keys.each_with_index do |col_name, j|
60
+ 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'])
61
+ operations.push(child_component)
62
+ end
63
+
64
+ request_url = URLS[:UPDATE_BLOCK]
65
+ request_body = build_payload(operations, request_ids)
66
+ response = HTTParty.post(
67
+ request_url,
68
+ body: request_body.to_json,
69
+ cookies: cookies,
70
+ headers: headers
71
+ )
72
+
73
+ 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
+ Please try again, and if issues persist open an issue in GitHub."; end
75
+
76
+ NotionAPI::CollectionViewRow.new(new_block_id, @parent_id, @collection_id, @view_id)
77
+ end
78
+
79
+ def add_property(name, type)
80
+ # ! add a property (column) to the table.
81
+ # ! name -> name of the property : ``str``
82
+ # ! type -> type of the property : ``str``
83
+ cookies = Core.options['cookies']
84
+ headers = Core.options['headers']
85
+
86
+ request_id = extract_id(SecureRandom.hex(16))
87
+ transaction_id = extract_id(SecureRandom.hex(16))
88
+ space_id = extract_id(SecureRandom.hex(16))
89
+
90
+ request_ids = {
91
+ request_id: request_id,
92
+ transaction_id: transaction_id,
93
+ space_id: space_id
94
+ }
95
+
96
+ # create updated schema
97
+ schema = extract_collection_schema(@collection_id, @view_id)
98
+ schema[name] = {
99
+ name: name,
100
+ type: type
101
+ }
102
+ new_schema = {
103
+ schema: schema
104
+ }
105
+
106
+ add_collection_property = Utils::CollectionViewComponents.add_collection_property(@collection_id, new_schema)
107
+
108
+ operations = [
109
+ add_collection_property
110
+ ]
111
+
112
+ request_url = URLS[:UPDATE_BLOCK]
113
+ request_body = build_payload(operations, request_ids)
114
+ response = HTTParty.post(
115
+ request_url,
116
+ body: request_body.to_json,
117
+ cookies: cookies,
118
+ headers: headers
119
+ )
120
+ 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}.
121
+ Please try again, and if issues persist open an issue in GitHub."; end
122
+
123
+ true
124
+ end
125
+
126
+ def row(row_id)
127
+ # ! retrieve a row from a CollectionView Table.
128
+ # ! row_id -> the ID for the row to retrieve: ``str``
129
+ clean_id = extract_id(row_id)
130
+
131
+ request_body = {
132
+ pageId: clean_id,
133
+ chunkNumber: 0,
134
+ limit: 100,
135
+ verticalColumns: false
136
+ }
137
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
138
+ schema = extract_collection_schema(@collection_id, @view_id)
139
+ keys = schema.keys
140
+ column_names = keys.map { |key| schema[key]['name'] }
141
+ i = 0
142
+ while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
143
+ return {} if i >= 10
144
+
145
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
146
+ i += 1
147
+ end
148
+ row_jsonified_response = jsonified_record_response['block'][clean_id]['value']['properties']
149
+ row_data = {}
150
+ keys.each_with_index { |key, idx| row_data[column_names[idx]] = row_jsonified_response[key] ? row_jsonified_response[key].flatten : [] }
151
+ row_data
152
+ end
153
+
154
+ def row_ids
155
+ # ! retrieve all Collection View table rows.
156
+ clean_id = extract_id(@id)
157
+
158
+ request_body = {
159
+ pageId: clean_id,
160
+ chunkNumber: 0,
161
+ limit: 100,
162
+ verticalColumns: false
163
+ }
164
+
165
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
166
+ i = 0
167
+ while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
168
+ return {} if i >= 10
169
+
170
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
171
+ i += 1
172
+ end
173
+
174
+ jsonified_record_response['collection_view'][@view_id]['value']['page_sort']
175
+ end
176
+
177
+ def rows
178
+ # ! returns all rows as instantiated class instances.
179
+ row_id_array = row_ids
180
+ parent_id = @parent_id
181
+ collection_id = @collection_id
182
+ view_id = @view_id
183
+
184
+ row_id_array.map { |row_id| NotionAPI::CollectionViewRow.new(row_id, parent_id, collection_id, view_id) }
185
+ end
186
+
187
+ private
188
+
189
+ def extract_collection_schema(collection_id, view_id)
190
+ # ! retrieve the collection scehma. Useful for 'building' the backbone for a table.
191
+ # ! collection_id -> the collection ID : ``str``
192
+ # ! view_id -> the view ID : ``str``
193
+ cookies = Core.options['cookies']
194
+ headers = Core.options['headers']
195
+
196
+ query_collection_hash = Utils::CollectionViewComponents.query_collection(collection_id, view_id, '')
197
+
198
+ request_url = URLS[:GET_COLLECTION]
199
+ response = HTTParty.post(
200
+ request_url,
201
+ body: query_collection_hash.to_json,
202
+ cookies: cookies,
203
+ headers: headers
204
+ )
205
+ response['recordMap']['collection'][collection_id]['value']['schema']
206
+ end
207
+ end
208
+ class CollectionViewRow < Core
209
+ @notion_type = 'table_row'
210
+ @type = 'table_row'
211
+
212
+ def type
213
+ NotionAPI::CollectionViewRow.notion_type
214
+ end
215
+
216
+ class << self
217
+ attr_reader :notion_type, :type, :parent_id
218
+ end
219
+
220
+ attr_reader :parent_id, :id
221
+ def initialize(id, parent_id, collection_id, view_id)
222
+ @id = id
223
+ @parent_id = parent_id
224
+ @collection_id = collection_id
225
+ @view_id = view_id
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # no use case for this yet.
4
+ class ColumnListBlock < BlockTemplate
5
+ @notion_type = 'column_list'
6
+ @type = 'column_list'
7
+
8
+ def type
9
+ NotionAPI::ColumnListBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module NotionAPI
2
+ # divider block: ---------
3
+ class DividerBlock < BlockTemplate
4
+ @notion_type = 'divider'
5
+ @type = 'divider'
6
+
7
+ def type
8
+ NotionAPI::DividerBlock.notion_type
9
+ end
10
+
11
+ class << self
12
+ attr_reader :notion_type, :type
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # Header block: H1
4
+ class HeaderBlock < BlockTemplate
5
+ @notion_type = 'header'
6
+ @type = 'header'
7
+
8
+ def type
9
+ NotionAPI::HeaderBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # good for visual information
4
+ class ImageBlock < BlockTemplate
5
+ @notion_type = 'image'
6
+ @type = 'image'
7
+
8
+ def type
9
+ NotionAPI::ImageBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module NotionAPI
2
+
3
+ # simiilar to code block but for mathematical functions.
4
+ class LatexBlock < BlockTemplate
5
+ @notion_type = 'equation'
6
+ @type = 'equation'
7
+
8
+ def type
9
+ NotionAPI::LatexBlock.notion_type
10
+ end
11
+
12
+ class << self
13
+ attr_reader :notion_type, :type
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module NotionAPI
2
+ # Numbered list Block: best for an ordered list
3
+ class NumberedBlock < BlockTemplate
4
+ @notion_type = 'numbered_list'
5
+ @type = 'numbered_list'
6
+
7
+ def type
8
+ NotionAPI::NumberedBlock.notion_type
9
+ end
10
+
11
+ class << self
12
+ attr_reader :notion_type, :type
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,130 @@
1
+
2
+ module NotionAPI
3
+
4
+ # Page Block, entrypoint for the application
5
+ class PageBlock < BlockTemplate
6
+ @notion_type = 'page'
7
+ @type = 'page'
8
+
9
+ def type
10
+ NotionAPI::PageBlock.notion_type
11
+ end
12
+
13
+ class << self
14
+ attr_reader :notion_type, :type
15
+ end
16
+
17
+ def get_block(url_or_id)
18
+ # ! retrieve a Notion Block and return its instantiated class object.
19
+ # ! url_or_id -> the block ID or URL : ``str``
20
+ get(url_or_id)
21
+ end
22
+
23
+ def get_collection(url_or_id)
24
+ # ! retrieve a Notion Collection and return its instantiated class object.
25
+ # ! url_or_id -> the block ID or URL : ``str``
26
+ clean_id = extract_id(url_or_id)
27
+
28
+ request_body = {
29
+ pageId: clean_id,
30
+ chunkNumber: 0,
31
+ limit: 100,
32
+ verticalColumns: false
33
+ }
34
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
35
+ i = 0
36
+ while jsonified_record_response.empty? || jsonified_record_response['block'].empty?
37
+ return {} if i >= 10
38
+
39
+ jsonified_record_response = get_all_block_info(clean_id, request_body)
40
+ i += 1
41
+ end
42
+ block_parent_id = extract_parent_id(clean_id, jsonified_record_response)
43
+ block_collection_id = extract_collection_id(clean_id, jsonified_record_response)
44
+ block_view_id = extract_view_ids(clean_id, jsonified_record_response).join
45
+ block_title = extract_collection_title(clean_id, block_collection_id, jsonified_record_response)
46
+
47
+ CollectionView.new(clean_id, block_title, block_parent_id, block_collection_id, block_view_id)
48
+ end
49
+
50
+ def create_collection(collection_type, collection_title, data)
51
+ # ! create a Notion Collection View and return its instantiated class object.
52
+ # ! _collection_type -> the type of collection to create : ``str``
53
+ # ! collection_title -> the title of the collection view : ``str``
54
+ # ! data -> JSON data to add to the table : ``str``
55
+
56
+ valid_types = %w[table board list timeline calendar gallery]
57
+ unless valid_types.include?(collection_type) ; raise ArgumentError, "That collection type is not yet supported. Try: #{valid_types.join}."; end
58
+ cookies = Core.options['cookies']
59
+ headers = Core.options['headers']
60
+
61
+ new_block_id = extract_id(SecureRandom.hex(16))
62
+ parent_id = extract_id(SecureRandom.hex(16))
63
+ collection_id = extract_id(SecureRandom.hex(16))
64
+ view_id = extract_id(SecureRandom.hex(16))
65
+
66
+ children = []
67
+ alive_blocks = []
68
+ data.each do |_row|
69
+ child = extract_id(SecureRandom.hex(16))
70
+ children.push(child)
71
+ alive_blocks.push(Utils::CollectionViewComponents.set_collection_blocks_alive(child, collection_id))
72
+ end
73
+
74
+ request_id = extract_id(SecureRandom.hex(16))
75
+ transaction_id = extract_id(SecureRandom.hex(16))
76
+ space_id = extract_id(SecureRandom.hex(16))
77
+
78
+ request_ids = {
79
+ request_id: request_id,
80
+ transaction_id: transaction_id,
81
+ space_id: space_id
82
+ }
83
+
84
+ create_collection_view = Utils::CollectionViewComponents.create_collection_view(new_block_id, collection_id, view_id)
85
+ configure_view = Utils::CollectionViewComponents.set_view_config(collection_type, new_block_id, view_id, children)
86
+
87
+ # returns the JSON and some useful column mappings...
88
+ column_data = Utils::CollectionViewComponents.set_collection_columns(collection_id, new_block_id, data)
89
+ configure_columns_hash = column_data[0]
90
+ column_mappings = column_data[1]
91
+ set_parent_alive_hash = Utils::BlockComponents.set_parent_to_alive(@id, new_block_id)
92
+ add_block_hash = Utils::BlockComponents.block_location_add(@id, @id, new_block_id, nil, 'listAfter')
93
+ new_block_edited_time = Utils::BlockComponents.last_edited_time(new_block_id)
94
+ collection_title_hash = Utils::CollectionViewComponents.set_collection_title(collection_title, collection_id)
95
+
96
+ operations = [
97
+ create_collection_view,
98
+ configure_view,
99
+ configure_columns_hash,
100
+ set_parent_alive_hash,
101
+ add_block_hash,
102
+ new_block_edited_time,
103
+ collection_title_hash
104
+ ]
105
+ operations << alive_blocks
106
+ all_ops = operations.flatten
107
+ data.each_with_index do |row, i|
108
+ child = children[i]
109
+ row.keys.each_with_index do |col_name, j|
110
+ child_component = Utils::CollectionViewComponents.insert_data(child, j.zero? ? 'title' : col_name, row[col_name], column_mappings[j])
111
+ all_ops.push(child_component)
112
+ end
113
+ end
114
+
115
+ request_url = URLS[:UPDATE_BLOCK]
116
+ request_body = build_payload(all_ops, request_ids)
117
+ response = HTTParty.post(
118
+ request_url,
119
+ body: request_body.to_json,
120
+ cookies: cookies,
121
+ headers: headers
122
+ )
123
+
124
+ 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}.
125
+ Please try again, and if issues persist open an issue in GitHub."; end
126
+
127
+ CollectionView.new(new_block_id, collection_title, parent_id, collection_id, view_id)
128
+ end
129
+ end
130
+ end