notion_ruby_mapping 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +503 -148
  3. data/env.yml.sample +1 -0
  4. data/examples/change_title.md +26 -0
  5. data/examples/renumbering_pages.md +20 -0
  6. data/examples/set_icon_to_all_icon_unsettled_pages.md +30 -0
  7. data/lib/notion_ruby_mapping/base.rb +129 -71
  8. data/lib/notion_ruby_mapping/checkbox_property.rb +27 -12
  9. data/lib/notion_ruby_mapping/created_by_property.rb +22 -10
  10. data/lib/notion_ruby_mapping/created_time_property.rb +16 -14
  11. data/lib/notion_ruby_mapping/database.rb +74 -10
  12. data/lib/notion_ruby_mapping/date_property.rb +67 -42
  13. data/lib/notion_ruby_mapping/email_property.rb +26 -16
  14. data/lib/notion_ruby_mapping/files_property.rb +40 -24
  15. data/lib/notion_ruby_mapping/formula_property.rb +51 -10
  16. data/lib/notion_ruby_mapping/last_edited_by_property.rb +22 -9
  17. data/lib/notion_ruby_mapping/last_edited_time_property.rb +16 -14
  18. data/lib/notion_ruby_mapping/list.rb +3 -0
  19. data/lib/notion_ruby_mapping/mention_object.rb +26 -1
  20. data/lib/notion_ruby_mapping/multi_select_property.rb +83 -21
  21. data/lib/notion_ruby_mapping/notion_cache.rb +17 -13
  22. data/lib/notion_ruby_mapping/number_property.rb +71 -10
  23. data/lib/notion_ruby_mapping/page.rb +32 -10
  24. data/lib/notion_ruby_mapping/payload.rb +21 -3
  25. data/lib/notion_ruby_mapping/people_property.rb +47 -19
  26. data/lib/notion_ruby_mapping/phone_number_property.rb +26 -15
  27. data/lib/notion_ruby_mapping/property.rb +142 -49
  28. data/lib/notion_ruby_mapping/property_cache.rb +31 -3
  29. data/lib/notion_ruby_mapping/query.rb +10 -0
  30. data/lib/notion_ruby_mapping/relation_property.rb +74 -21
  31. data/lib/notion_ruby_mapping/rich_text_array.rb +81 -0
  32. data/lib/notion_ruby_mapping/rich_text_object.rb +58 -1
  33. data/lib/notion_ruby_mapping/rich_text_property.rb +12 -1
  34. data/lib/notion_ruby_mapping/rollup_property.rb +82 -10
  35. data/lib/notion_ruby_mapping/select_property.rb +88 -13
  36. data/lib/notion_ruby_mapping/text_object.rb +0 -51
  37. data/lib/notion_ruby_mapping/text_property.rb +19 -45
  38. data/lib/notion_ruby_mapping/title_property.rb +12 -1
  39. data/lib/notion_ruby_mapping/url_property.rb +26 -15
  40. data/lib/notion_ruby_mapping/user_object.rb +4 -4
  41. data/lib/notion_ruby_mapping/version.rb +1 -1
  42. data/lib/notion_ruby_mapping.rb +2 -1
  43. data/tools/an +103 -0
  44. metadata +7 -2
data/env.yml.sample CHANGED
@@ -12,3 +12,4 @@ db_update_page: "206ffaa277744a99baf593e28730240c"
12
12
  user_hkob: "2200a911-6a96-44bb-bd38-6bfb1e01b9f6"
13
13
  parent1_page: "860753bb6d1f48de96211fa6e0e31f82"
14
14
  parent_database: "1d6b1040a9fb48d99a3d041429816e9f"
15
+ created_database: "c7697137d49f49c2bbcdd6a665c4f921"
@@ -0,0 +1,26 @@
1
+ # Change title
2
+
3
+ The following code update the page title.
4
+
5
+ #### Pattern 1 (replace existing text partially)
6
+
7
+ ```Ruby
8
+ page = Page.find page_id # API access
9
+ print page.title # -> ABC\nDEF
10
+ tp = page.properties["Title"]
11
+ tp[1].text = "GHI"
12
+ page.save # API access
13
+ print page.title # -> ABC\nGHI
14
+ ```
15
+
16
+ #### Pattern 2 (replace all text)
17
+
18
+ ```Ruby
19
+ page = Page.new id: page_id, assign: [TitleProperty, "Title"]
20
+ tp = page.properties["Title"]
21
+ tp << TextObject.new("JKL")
22
+ page.save # API access
23
+ print page.title # -> JKL
24
+ ```
25
+ ---
26
+ [Return to README.md](../README.md#2-example-code)
@@ -0,0 +1,20 @@
1
+ # Renumbering pages
2
+
3
+ The following code sets serial numbers to the pages whose title is not empty in ascending order of titles.
4
+
5
+ ```Ruby
6
+ db = Database.new id: database_id, assign: [RichTextProperty, "TextTitle"]
7
+ tp = db.properties["TextTitle"]
8
+ query = tp.filter_is_not_empty.ascending(tp)
9
+ db.query_database(tp.filter_is_not_empty.ascending(tp)).each.with_index(1) do |page, index|
10
+ page.properties["NumberTitle"].number = index
11
+ page.save
12
+ end
13
+ ```
14
+
15
+ | After execution |
16
+ |-----------------------------------------------|
17
+ | ![After exuecution](../images/serial_number.png) |
18
+
19
+ ---
20
+ [Return to README.md](../README.md#2-example-code)
@@ -0,0 +1,30 @@
1
+ # Set icon to all icon unsettled pages
2
+
3
+ The following code sets a "💿" icon on all unset pages in the database.
4
+
5
+ ```Ruby
6
+ require "notion_ruby_mapping"
7
+
8
+ include NotionRubyMapping
9
+
10
+ token = ENV["NOTION_API_TOKEN"]
11
+ database_id = ENV["DATABASE_ID"]
12
+
13
+ NotionCache.instance.create_client token
14
+
15
+ db = Database.new id: database_id
16
+ db.query_database.each do |page|
17
+ unless page.icon
18
+ page.set_icon(emoji: "💿")
19
+ page.save
20
+ p page.id
21
+ end
22
+ end
23
+ ```
24
+
25
+ |Before execution|After execution|
26
+ |---|---|
27
+ |![Before execution](../images/pre_set_icon.png)|![After execution](../images/post_set_icon.png)|
28
+
29
+ ---
30
+ [Return to README.md](../README.md#2-example-code)
@@ -3,6 +3,8 @@
3
3
  module NotionRubyMapping
4
4
  # Notion Base object (Parent of Page / Database / List)
5
5
  class Base
6
+ #### Public announced methods
7
+
6
8
  # @param [Hash, nil] json
7
9
  # @param [String, nil] id
8
10
  # @param [Array<Property, Class, String>] assign
@@ -15,31 +17,58 @@ module NotionRubyMapping
15
17
 
16
18
  @payload = Payload.new(parent && {"parent" => parent})
17
19
  @property_cache = nil
20
+ @created_time = nil
21
+ @last_edited_time = nil
18
22
  assign.each_slice(2) { |(klass, key)| assign_property(klass, key) }
19
23
  end
20
24
  attr_reader :json, :id
21
25
 
22
- # @param [Hash, Notion::Messages] json
23
- # @return [NotionRubyMapping::Base]
24
- def self.create_from_json(json)
25
- case json["object"]
26
- when "page"
27
- Page.new json: json
28
- when "database"
29
- Database.new json: json
30
- when "list"
31
- List.new json: json
32
- when "block"
33
- Block.new json: json
26
+ # @param [String] key
27
+ # @return [NotionRubyMapping::PropertyCache, Hash] obtained Page value or PropertyCache
28
+ def [](key)
29
+ unless @json
30
+ raise StandardError, "Unknown id" if @id.nil?
31
+
32
+ reload
33
+ end
34
+ case key
35
+ when "properties"
36
+ properties
34
37
  else
35
- raise StandardError, json.inspect
38
+ @json[key]
36
39
  end
37
40
  end
38
41
 
42
+ # @return [NotionRubyMapping::CreatedTimeProperty]
43
+ def created_time
44
+ @created_time ||= CreatedTimeProperty.new("__timestamp__")
45
+ end
46
+
47
+ # @return [TrueClass, FalseClass] true if Database object
48
+ def database?
49
+ is_a? Database
50
+ end
51
+
52
+ # @return [Hash, nil] obtained Hash
53
+ def icon
54
+ self["icon"]
55
+ end
56
+
57
+ # @return [NotionRubyMapping::LastEditedTimeProperty]
58
+ def last_edited_time
59
+ @last_edited_time ||= LastEditedTimeProperty.new("__timestamp__")
60
+ end
61
+
62
+ # @return [Boolean] true if new record
39
63
  def new_record?
40
64
  @new_record
41
65
  end
42
66
 
67
+ # @return [TrueClass, FalseClass] true if Page object
68
+ def page?
69
+ is_a? Page
70
+ end
71
+
43
72
  # @return [NotionRubyMapping::PropertyCache] get or created PropertyCache object
44
73
  def properties
45
74
  unless @property_cache
@@ -48,30 +77,68 @@ module NotionRubyMapping
48
77
 
49
78
  reload
50
79
  end
51
- @property_cache = PropertyCache.new json_properties
80
+ @property_cache = PropertyCache.new json_properties, base_type: database? ? :database : :page
52
81
  end
53
82
  @property_cache
54
83
  end
55
84
 
85
+ # @return [NotionRubyMapping::Base, String]
86
+ def save(dry_run: false)
87
+ if dry_run
88
+ @new_record ? create(dry_run: true) : update(dry_run: true)
89
+ else
90
+ @new_record ? create : update
91
+ @property_cache.clear_will_update
92
+ @payload.clear
93
+ self
94
+ end
95
+ end
96
+
97
+ # @param [String] emoji
98
+ # @param [String] url
99
+ # @return [NotionRubyMapping::Base]
100
+ def set_icon(emoji: nil, url: nil)
101
+ @payload.set_icon(emoji: emoji, url: url) if page? || database?
102
+ self
103
+ end
104
+
56
105
  # @return [String] title
57
106
  def title
58
107
  properties.select { |p| p.is_a? TitleProperty }.map(&:full_text).join ""
59
108
  end
60
109
 
61
- # @return [NotionRubyMapping::Base] reloaded self
62
- def reload
63
- update_json reload_json
64
- self
65
- end
66
-
67
- # @return [NotionRubyMapping::Base]
68
- def save
69
- @new_record ? create : update
110
+ ### Not public announced methods
111
+
112
+ # @param [Hash, Notion::Messages] json
113
+ # @return [NotionRubyMapping::Base]
114
+ def self.create_from_json(json)
115
+ case json["object"]
116
+ when "page"
117
+ Page.new json: json
118
+ when "database"
119
+ Database.new json: json
120
+ when "list"
121
+ List.new json: json
122
+ when "block"
123
+ Block.new json: json
124
+ else
125
+ raise StandardError, json.inspect
126
+ end
70
127
  end
71
128
 
72
- # @return [Hash] json properties
73
- def json_properties
74
- @json && @json["properties"]
129
+ # @param [NotionRubyMapping::Property] klass
130
+ # @param [String] title
131
+ # @return [NotionRubyMapping::Property] generated property
132
+ def assign_property(klass, title)
133
+ @property_cache ||= PropertyCache.new({}, base_type: database? ? :database : :page)
134
+
135
+ property = if database?
136
+ klass.new(title, will_update: new_record?, base_type: :database)
137
+ else
138
+ klass.new(title, will_update: true, base_type: :page)
139
+ end
140
+ @property_cache.add_property property
141
+ property
75
142
  end
76
143
 
77
144
  # @return [NotionRubyMapping::List]
@@ -79,74 +146,65 @@ module NotionRubyMapping
79
146
  @children ||= @nc.block_children(id)
80
147
  end
81
148
 
82
- # @param [Hash] json
83
- # @return [NotionRubyMapping::Base]
84
- def update_json(json)
85
- raise StandardError, json.inspect unless json["object"] != "error" && @json.nil? || @json["type"] == json["type"]
149
+ # @return [Hash] created json for update page
150
+ def property_values_json
151
+ @payload.property_values_json @property_cache
152
+ end
86
153
 
87
- @json = json
88
- @id = @nc.hex_id(@json["id"])
89
- restore_from_json
154
+ # @return [NotionRubyMapping::Base] reloaded self
155
+ def reload
156
+ update_json reload_json
90
157
  self
91
158
  end
92
159
 
160
+ # @return [NotionRubyMapping::Base]
93
161
  def restore_from_json
94
- @payload.clear
95
162
  return if (ps = @json["properties"]).nil?
96
163
 
97
164
  properties.json = json_properties
98
- return unless is_a? Page
165
+ return unless is_a?(Page) || is_a?(Database)
99
166
 
100
167
  ps.each do |key, json|
101
168
  properties[key].update_from_json json
102
169
  end
170
+ self
103
171
  end
104
172
 
105
- # @param [String] emoji
106
- # @param [String] url
173
+ # @param [Hash] json
107
174
  # @return [NotionRubyMapping::Base]
108
- def set_icon(emoji: nil, url: nil)
109
- if is_a?(Page) || is_a?(Database)
110
- @payload.set_icon(emoji: emoji, url: url)
111
- end
175
+ def update_json(json)
176
+ raise StandardError, json.inspect unless json["object"] != "error" && @json.nil? || @json["type"] == json["type"]
177
+
178
+ @json = json
179
+ @id = @nc.hex_id(@json["id"])
180
+ restore_from_json
112
181
  self
113
182
  end
114
183
 
115
- # @param [String] key
116
- # @return [NotionRubyMapping::PropertyCache, Hash] obtained Page value or PropertyCache
117
- def [](key)
118
- unless @json
119
- raise StandardError, "Unknown id" if @id.nil?
120
-
121
- reload
122
- end
123
- case key
124
- when "properties"
125
- properties
126
- else
127
- @json[key]
128
- end
184
+ # protected
185
+ # @return [Hash] json properties
186
+ def json_properties
187
+ @json && @json["properties"]
129
188
  end
130
189
 
131
- # @return [Hash, nil] obtained Hash
132
- def icon
133
- self["icon"]
190
+ # @param [Object] method
191
+ # @param [Object] path
192
+ # @param [nil] json
193
+ def self.dry_run_script(method, path, json = nil)
194
+ shell = [
195
+ "#!/bin/sh\ncurl #{method == :get ? "" : "-X #{method.to_s.upcase}"} 'https://api.notion.com/#{path}'",
196
+ " -H 'Notion-Version: 2022-02-22'",
197
+ " -H 'Authorization: Bearer '\"$NOTION_API_KEY\"''",
198
+ ]
199
+ shell << " -H 'Content-Type: application/json'" unless path == :get
200
+ shell << " --data '#{JSON.generate json}'" if json
201
+ shell.join(" \\\n")
134
202
  end
135
203
 
136
- # @param [Property, Class] klass
137
- # @param [String] title
138
- # @return [Property] generated property
139
- def assign_property(klass, title)
140
- @property_cache ||= PropertyCache.new {}
141
-
142
- property = klass.new(title, will_update: true)
143
- @property_cache.add_property property
144
- property
145
- end
204
+ protected
146
205
 
147
- # @return [Hash] created json
148
- def property_values_json
149
- @payload.property_values_json @property_cache&.property_values_json
206
+ def dry_run_script(method, path, json_method)
207
+ self.class.dry_run_script method, path, send(json_method)
150
208
  end
151
209
  end
152
210
  end
@@ -6,30 +6,45 @@ module NotionRubyMapping
6
6
  include EqualsDoesNotEqual
7
7
  TYPE = "checkbox"
8
8
 
9
- # @param [String] name Property name
10
- # @param [Boolean] checkbox Number value (optional)
11
- def initialize(name, will_update: false, checkbox: false)
12
- super name, will_update: will_update
13
- @checkbox = checkbox
9
+ ### Public announced methods
10
+
11
+ ## Common methods
12
+
13
+ # @return [Boolean, Hash]
14
+ def checkbox
15
+ @json
14
16
  end
15
- attr_reader :checkbox
17
+
18
+ ## Page property only methods
16
19
 
17
20
  # @param [Boolean] flag
18
21
  # @return [TrueClass, FalseClass] settled value
19
22
  def checkbox=(flag)
20
23
  @will_update = true
21
- @checkbox = flag
24
+ @json = flag
22
25
  end
23
26
 
24
- # @param [Hash] json
25
- def update_from_json(json)
26
- @will_update = false
27
- @checkbox = json["checkbox"]
27
+ ### Not public announced methods
28
+
29
+ ## Common methods
30
+
31
+ # @param [String] name Property name
32
+ # @param [Boolean, Hash] json
33
+ def initialize(name, will_update: false, base_type: :page, json: nil)
34
+ super name, will_update: will_update, base_type: base_type
35
+ @json = if database?
36
+ json || {}
37
+ else
38
+ json || false
39
+ end
28
40
  end
29
41
 
42
+ ## Page property only methods
43
+
30
44
  # @return [Hash]
31
45
  def property_values_json
32
- {@name => {"checkbox" => @checkbox, "type" => "checkbox"}}
46
+ assert_page_property __method__
47
+ {@name => {"checkbox" => @json, "type" => "checkbox"}}
33
48
  end
34
49
  end
35
50
  end
@@ -5,24 +5,36 @@ module NotionRubyMapping
5
5
  class CreatedByProperty < MultiProperty
6
6
  TYPE = "created_by"
7
7
 
8
+ ### Public announced methods
9
+
10
+ ## Common methods
11
+
12
+ # @return [NotionRubyMapping::UserObject, Hash]
13
+ def created_by
14
+ @json
15
+ end
16
+
17
+ ### Not public announced methods
18
+
19
+ ## Common methods
20
+
8
21
  # @param [String] name Property name
9
22
  # @param [String] user_id user_id (optional)
10
23
  # @param [Hash] json json (optional)
11
- def initialize(name, json: nil, user_id: nil)
12
- super name, will_update: false
13
- @user = UserObject.new user_id: user_id, json: json
24
+ def initialize(name, will_update: false, base_type: :page, json: nil, user_id: nil)
25
+ super name, will_update: will_update, base_type: base_type
26
+ @json = if database?
27
+ json || {}
28
+ else
29
+ UserObject.new user_id: user_id, json: json
30
+ end
14
31
  end
15
- attr_reader :user
16
32
 
17
33
  # @param [Hash] json
18
34
  def update_from_json(json)
19
35
  @will_update = false
20
- @user = UserObject.new json: json["created_by"]
21
- end
22
-
23
- # @return [Hash] {} created_time cannot be updated
24
- def property_values_json
25
- {}
36
+ cb = json["created_by"]
37
+ @json = database? ? cb : UserObject.new(json: cb)
26
38
  end
27
39
  end
28
40
  end
@@ -5,23 +5,25 @@ module NotionRubyMapping
5
5
  class CreatedTimeProperty < DateBaseProperty
6
6
  TYPE = "created_time"
7
7
 
8
- # @param [String] name Property name
9
- # @param [String] created_time created_time value (optional)
10
- def initialize(name, created_time: nil)
11
- super name, will_update: false
12
- @created_time = created_time
13
- end
14
- attr_reader :created_time
8
+ ### Public announced methods
9
+
10
+ ## Common methods
15
11
 
16
- # @param [Hash] json
17
- def update_from_json(json)
18
- @will_update = false
19
- @created_time = json["created_time"]
12
+ # @return [Date, Hash]
13
+ def created_time
14
+ @json
20
15
  end
21
16
 
22
- # @return [Hash] {} created_time cannot be updated
23
- def property_values_json
24
- {}
17
+ ### Not public announced methods
18
+
19
+ ## Common methods
20
+
21
+ # @param [String] name Property name
22
+ # @param [String] json created_time value (optional)
23
+ def initialize(name, will_update: false, base_type: :page, json: nil)
24
+ super name, will_update: will_update, base_type: base_type
25
+ @json = json
26
+ @json ||= {} if database?
25
27
  end
26
28
  end
27
29
  end
@@ -3,19 +3,28 @@
3
3
  module NotionRubyMapping
4
4
  # Notion database
5
5
  class Database < Base
6
- def self.find(id)
7
- NotionCache.instance.database id
8
- end
6
+ ### Public announced methods
9
7
 
10
- # @param [NotionRubyMapping::Query] query object
11
- def query_database(query = Query.new)
12
- response = @nc.database_query @id, query
13
- List.new json: response, database: self, query: query
8
+ # @param [String] id
9
+ # @return [NotionRubyMapping::Database, String]
10
+ def self.find(id, dry_run: false)
11
+ nc = NotionCache.instance
12
+ if dry_run
13
+ dry_run_script :get, nc.database_path(id)
14
+ else
15
+ nc.database id
16
+ end
14
17
  end
15
18
 
16
- # @return [NotionRubyMapping::Base]
17
- def update
18
- update_json @nc.update_database_request(@id, property_values_json)
19
+ # @return [NotionRubyMapping::Property]
20
+ # @param [Class] klass
21
+ # @param [String] title
22
+ def add_property(klass, title)
23
+ prop = assign_property klass, title
24
+ yield prop if block_given?
25
+ @payload.merge_property prop.property_schema_json
26
+ prop.clear_will_update
27
+ prop
19
28
  end
20
29
 
21
30
  # @param [Array<Property, Class, String>] assign
@@ -24,11 +33,66 @@ module NotionRubyMapping
24
33
  Page.new assign: assign, parent: {"database_id" => @id}
25
34
  end
26
35
 
36
+ # @return [NotionRubyMapping::RichTextArray]
37
+ def database_title
38
+ @database_title ||= RichTextArray.new "title", json: (self["title"]), will_update: new_record?
39
+ end
40
+
41
+ def property_schema_json
42
+ @payload.property_schema_json @property_cache, database_title
43
+ end
44
+
45
+ # @return [Hash] created json for update database
46
+ def property_values_json
47
+ @payload.property_values_json @property_cache, database_title
48
+ end
49
+
50
+ # @param [NotionRubyMapping::Query] query object
51
+ # @return [NotionRubyMapping::List, String]
52
+ def query_database(query = Query.new, dry_run: false)
53
+ if dry_run
54
+ Base.dry_run_script :post, @nc.query_database_path(@id), query.query_json
55
+ else
56
+ response = @nc.database_query @id, query
57
+ List.new json: response, database: self, query: query
58
+ end
59
+ end
60
+
61
+ # @param [Array] names
62
+ # @return [Array<NotionRubyMapping::Property>]
63
+ def remove_properties(*names)
64
+ names.map { |n| properties[n] }.each(&:remove)
65
+ end
66
+
67
+ # @return [Hash] created json for update database
68
+ def update_property_schema_json
69
+ @payload.update_property_schema_json @property_cache, database_title
70
+ end
71
+
27
72
  protected
28
73
 
74
+ def create(dry_run: false)
75
+ if dry_run
76
+ dry_run_script :post, @nc.databases_path, :property_schema_json
77
+ else
78
+ json = @nc.create_database_request(property_schema_json)
79
+ @new_record = false
80
+ update_json json
81
+ end
82
+ end
83
+
29
84
  # @return [Hash]
30
85
  def reload_json
31
86
  @nc.database_request @id
32
87
  end
88
+
89
+ # @return [NotionRubyMapping::Base, String]
90
+ def update(dry_run: false)
91
+ if dry_run
92
+ dry_run_script :patch, @nc.database_path(@id), :update_property_schema_json
93
+ else
94
+ update_json @nc.update_database_request(@id, update_property_schema_json)
95
+ end
96
+ end
33
97
  end
34
98
  end