notion 1.0.1 → 1.0.2

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.
@@ -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