notion_orbit 0.0.1
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.
- checksums.yaml +7 -0
- data/.env.sample +5 -0
- data/.github/CODE_OF_CONDUCT.md +134 -0
- data/.github/CONTRIBUTING.md +69 -0
- data/.github/workflows/CI.yml +25 -0
- data/.gitignore +34 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +115 -0
- data/LICENSE +21 -0
- data/README.md +108 -0
- data/bin/console +16 -0
- data/bin/notion_orbit +28 -0
- data/bin/setup +8 -0
- data/docs/database-id-location.png +0 -0
- data/docs/new-note-screenshot.png +0 -0
- data/docs/setup-table-for-orbit.png +0 -0
- data/docs/setup.md +17 -0
- data/docs/ways-to-use.png +0 -0
- data/lib/notion_orbit.rb +12 -0
- data/lib/notion_orbit/client.rb +55 -0
- data/lib/notion_orbit/interactions/note.rb +37 -0
- data/lib/notion_orbit/notion.rb +42 -0
- data/lib/notion_orbit/notion_objects/block.rb +60 -0
- data/lib/notion_orbit/notion_objects/block_types/bulleted_list_item.rb +15 -0
- data/lib/notion_orbit/notion_objects/block_types/heading_1.rb +11 -0
- data/lib/notion_orbit/notion_objects/block_types/heading_2.rb +11 -0
- data/lib/notion_orbit/notion_objects/block_types/heading_3.rb +11 -0
- data/lib/notion_orbit/notion_objects/block_types/numbered_list_item.rb +15 -0
- data/lib/notion_orbit/notion_objects/block_types/paragraph.rb +15 -0
- data/lib/notion_orbit/notion_objects/block_types/to_do.rb +11 -0
- data/lib/notion_orbit/notion_objects/block_types/unsupported.rb +11 -0
- data/lib/notion_orbit/notion_objects/blocks.rb +18 -0
- data/lib/notion_orbit/notion_objects/rich_text.rb +36 -0
- data/lib/notion_orbit/orbit.rb +16 -0
- data/lib/notion_orbit/services/notion.rb +57 -0
- data/lib/notion_orbit/services/orbit.rb +73 -0
- data/lib/notion_orbit/version.rb +5 -0
- data/notion_orbit.gemspec +43 -0
- data/scripts/check_notes.rb +17 -0
- metadata +201 -0
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "dotenv/load"
|
6
|
+
require "notion_orbit"
|
7
|
+
|
8
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
9
|
+
# with your gem easier. You can also use a different console, if you like.
|
10
|
+
|
11
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
12
|
+
# require "pry"
|
13
|
+
# Pry.start
|
14
|
+
|
15
|
+
require "irb"
|
16
|
+
IRB.start(__FILE__)
|
data/bin/notion_orbit
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
check_notes = false
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
choices = OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: notion_orbit --check-notes"
|
10
|
+
opts.on("-h", "--help", "Prints help instructions") do
|
11
|
+
puts opts
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
opts.on("--check-notes", "Check for new notes") do
|
15
|
+
check_notes = true
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
$LOAD_PATH.unshift(File.expand_path('../lib/notion_orbit', __dir__))
|
20
|
+
|
21
|
+
require_relative '../lib/notion_orbit'
|
22
|
+
require_relative '../scripts/check_notes'
|
23
|
+
|
24
|
+
if check_notes
|
25
|
+
puts "Checking for new notes and posting them to your Orbit workspace..."
|
26
|
+
ARGV[0] = 'render'
|
27
|
+
NotionOrbit::Scripts::CheckNotes.start(ARGV)
|
28
|
+
end
|
data/bin/setup
ADDED
Binary file
|
Binary file
|
Binary file
|
data/docs/setup.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
<small><a href="../README.md">Back to README</a></small>
|
2
|
+
|
3
|
+
# First Time Setup
|
4
|
+
|
5
|
+
During the setup, we will need to create a new Notion integration which will allow this library to interact with the platform. This process takes about 2 minutes to finish. The application will contain an API secret which we should take note of for later.
|
6
|
+
|
7
|
+
1. Head to [Notion Integrations](https://www.notion.so/my-integrations) and login in to your account.
|
8
|
+
2. Click on the "+ New Integration" button on the left-hand side of the page. *Note: You must have admin access to your Notion workspace.*
|
9
|
+
3. Fill out the details in the request form and press the "Submit" button.
|
10
|
+
4. Save the "Internal Integration Token" from Notion. You will use it in this application. Do not share it with others and keep it in a secure location.
|
11
|
+
5. Make sure that the "Integration Type" is set to "Internal Integration".
|
12
|
+
6. Click "Save changes".
|
13
|
+
7. You must add your integration to the database in your Notion workspace that you wish to fetch notes from.
|
14
|
+
* From the top navigation bar in your Notion database view press the "Share" button
|
15
|
+
* Find your integration by the name you gave it in the request form
|
16
|
+
* Select the integration and click "Invite"<br/>
|
17
|
+

|
Binary file
|
data/lib/notion_orbit.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
require_relative "notion_orbit/version"
|
5
|
+
require "notion-ruby-client"
|
6
|
+
|
7
|
+
module NotionOrbit
|
8
|
+
loader = Zeitwerk::Loader.new
|
9
|
+
loader.tag = File.basename(__FILE__, ".rb")
|
10
|
+
loader.push_dir(__dir__)
|
11
|
+
loader.setup
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dotenv/load"
|
4
|
+
require "net/http"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
# Create a client to log Notion database activities in your Orbit workspace
|
8
|
+
# Credentials can either be passed in to the instance or be loaded
|
9
|
+
# from environment variables
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# client = NotionOrbit::Client.new
|
13
|
+
#
|
14
|
+
# @option params [String] :orbit_api_key
|
15
|
+
# The API key for the Orbit API
|
16
|
+
#
|
17
|
+
# @option params [String] :orbit_workspace
|
18
|
+
# The workspace ID for the Orbit workspace
|
19
|
+
#
|
20
|
+
# @option params [String] :notion_api_key
|
21
|
+
# The API key for Notion
|
22
|
+
#
|
23
|
+
# @option params [String] :notion_workspace_slug
|
24
|
+
# The Notion workspace slug
|
25
|
+
#
|
26
|
+
# @option params [String] :notion_database_id
|
27
|
+
# The Notion database ID
|
28
|
+
#
|
29
|
+
# @param [Hash] params
|
30
|
+
#
|
31
|
+
# @return [NotionOrbit::Client]
|
32
|
+
#
|
33
|
+
module NotionOrbit
|
34
|
+
class Client
|
35
|
+
attr_accessor :orbit_api_key, :orbit_workspace, :notion_database_id, :notion_api_key, :notion_workspace_slug
|
36
|
+
|
37
|
+
def initialize(params = {})
|
38
|
+
@orbit_api_key = params.fetch(:orbit_api_key, ENV["ORBIT_API_KEY"])
|
39
|
+
@orbit_workspace = params.fetch(:orbit_workspace, ENV["ORBIT_WORKSPACE_ID"])
|
40
|
+
@notion_api_key = params.fetch(:notion_api_key, ENV["NOTION_API_KEY"])
|
41
|
+
@notion_database_id = params.fetch(:notion_database_id, ENV["NOTION_DATABASE_ID"])
|
42
|
+
@notion_workspace_slug = params.fetch(:notion_workspace_slug, ENV["NOTION_WORKSPACE_SLUG"])
|
43
|
+
end
|
44
|
+
|
45
|
+
def notes
|
46
|
+
NotionOrbit::Notion.new(
|
47
|
+
orbit_api_key: @orbit_api_key,
|
48
|
+
orbit_workspace: @orbit_workspace,
|
49
|
+
notion_api_key: @notion_api_key,
|
50
|
+
notion_database_id: @notion_database_id,
|
51
|
+
notion_workspace_slug: @notion_workspace_slug
|
52
|
+
).process_notes
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module NotionOrbit
|
6
|
+
module Interactions
|
7
|
+
class Note
|
8
|
+
def initialize(note:, orbit_api_key:, orbit_workspace:, notion_api_key:)
|
9
|
+
@note = note
|
10
|
+
@orbit_workspace = orbit_workspace
|
11
|
+
@orbit_api_key = orbit_api_key
|
12
|
+
@notion_api_key = notion_api_key
|
13
|
+
|
14
|
+
after_initialize!
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_initialize!
|
18
|
+
orbit_service = NotionOrbit::Services::Orbit.new(orbit_workspace: @orbit_workspace, orbit_api_key: @orbit_api_key)
|
19
|
+
notion_service = NotionOrbit::Services::Notion.new(token: @notion_api_key)
|
20
|
+
|
21
|
+
orbit_service.send_note(
|
22
|
+
member_slug: @note[:member_slug],
|
23
|
+
api_key: @orbit_api_key,
|
24
|
+
content: @note[:content]
|
25
|
+
)
|
26
|
+
|
27
|
+
notion_service.mark_note_as_synced(@note[:page_id], orbit_note_url(@note[:member_slug]))
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def orbit_note_url(member_slug)
|
33
|
+
"https://app.orbit.love/#{@orbit_workspace}/members/#{member_slug}?type=notes"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NotionOrbit
|
4
|
+
class Notion
|
5
|
+
def initialize(params = {})
|
6
|
+
@orbit_api_key = params.fetch(:orbit_api_key)
|
7
|
+
@orbit_workspace = params.fetch(:orbit_workspace)
|
8
|
+
@notion_api_key = params.fetch(:notion_api_key)
|
9
|
+
@notion_database_id = params.fetch(:notion_database_id)
|
10
|
+
@notion_workspace_slug = params.fetch(:notion_workspace_slug)
|
11
|
+
end
|
12
|
+
|
13
|
+
def process_notes
|
14
|
+
notion_service = NotionOrbit::Services::Notion.new(token: @notion_api_key)
|
15
|
+
orbit_service = NotionOrbit::Services::Orbit.new(orbit_workspace: @orbit_workspace, orbit_api_key: @orbit_api_key)
|
16
|
+
|
17
|
+
notes = notion_service.notes(database_id: @notion_database_id)
|
18
|
+
|
19
|
+
notes.each do |note|
|
20
|
+
next if note[:properties][:email].nil? || note[:properties][:email] == ""
|
21
|
+
|
22
|
+
member_slug = orbit_service.member_slug(email: note[:properties][:email])
|
23
|
+
next if member_slug == "" || member_slug.nil?
|
24
|
+
|
25
|
+
NotionOrbit::Orbit.call(
|
26
|
+
type: "note",
|
27
|
+
data: {
|
28
|
+
note: {
|
29
|
+
email: note[:properties][:email],
|
30
|
+
member_slug: member_slug,
|
31
|
+
page_id: note[:properties][:page_id],
|
32
|
+
content: note[:content]
|
33
|
+
}
|
34
|
+
},
|
35
|
+
orbit_workspace: @orbit_workspace,
|
36
|
+
orbit_api_key: @orbit_api_key,
|
37
|
+
notion_api_key: @notion_api_key
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module NotionOrbit
|
2
|
+
module NotionObjects
|
3
|
+
class Block
|
4
|
+
class << self
|
5
|
+
def new_from_raw_block(raw_block, indentation: 0)
|
6
|
+
klass = case raw_block.type
|
7
|
+
when 'bulleted_list_item'
|
8
|
+
NotionOrbit::NotionObjects::BlockTypes::BulletedListItem
|
9
|
+
when 'heading_1'
|
10
|
+
NotionOrbit::NotionObjects::BlockTypes::Heading1
|
11
|
+
when 'heading_2'
|
12
|
+
NotionOrbit::NotionObjects::BlockTypes::Heading2
|
13
|
+
when 'heading_3'
|
14
|
+
NotionOrbit::NotionObjects::BlockTypes::Heading3
|
15
|
+
when 'numbered_list_item'
|
16
|
+
NotionOrbit::NotionObjects::BlockTypes::NumberedListItem
|
17
|
+
when 'paragraph'
|
18
|
+
NotionOrbit::NotionObjects::BlockTypes::Paragraph
|
19
|
+
when 'to_do'
|
20
|
+
NotionOrbit::NotionObjects::BlockTypes::ToDo
|
21
|
+
else
|
22
|
+
NotionOrbit::NotionObjects::BlockTypes::Unsupported
|
23
|
+
end
|
24
|
+
klass.new(raw_block, indentation)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(raw_block, indentation)
|
29
|
+
@raw_block = raw_block
|
30
|
+
@id = raw_block.id
|
31
|
+
@type = raw_block.type
|
32
|
+
@has_children = raw_block.has_children
|
33
|
+
@indentation = indentation
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_markdown
|
37
|
+
markdown = @raw_block[@type].text.map do |rich_text|
|
38
|
+
NotionOrbit::NotionObjects::RichText.new(rich_text).to_markdown
|
39
|
+
end.join
|
40
|
+
|
41
|
+
if @has_children
|
42
|
+
raw_children = notion_service.client.block_children(id: @id).results
|
43
|
+
children_indentation = indent_children? ? @indentation + 2 : @indentation
|
44
|
+
children_blocks = Blocks.new(raw_children, indentation: children_indentation)
|
45
|
+
markdown += "\n\n" + children_blocks.to_markdown
|
46
|
+
end
|
47
|
+
|
48
|
+
markdown
|
49
|
+
end
|
50
|
+
|
51
|
+
def indent_children?
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def notion_service
|
56
|
+
@notion_service ||= NotionOrbit::Services::Notion.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module NotionOrbit
|
2
|
+
module NotionObjects
|
3
|
+
class Blocks
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_accessor :blocks
|
7
|
+
|
8
|
+
def initialize(raw_blocks, indentation: 0)
|
9
|
+
@blocks = raw_blocks.map{ |raw_block| Block.new_from_raw_block(raw_block, indentation: indentation) }
|
10
|
+
@indentation = indentation
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_markdown
|
14
|
+
@blocks.map { |block| " " * @indentation + block.to_markdown }.join("\n").rstrip.gsub("\n","\\n")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module NotionOrbit
|
2
|
+
module NotionObjects
|
3
|
+
class RichText
|
4
|
+
def initialize(raw_rich_text)
|
5
|
+
@raw_rich_text = raw_rich_text
|
6
|
+
@type = raw_rich_text.type
|
7
|
+
@annotations = raw_rich_text.annotations
|
8
|
+
@text = raw_rich_text.text
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_markdown
|
12
|
+
return "" unless @type == 'text'
|
13
|
+
markdown = @text.content
|
14
|
+
markdown = apply_link(markdown) unless @text.link.nil?
|
15
|
+
markdown = apply_annotations(markdown)
|
16
|
+
markdown
|
17
|
+
end
|
18
|
+
|
19
|
+
def apply_link(content)
|
20
|
+
@text.link.nil? ? content : "[#{content}](#{@text.link.url})"
|
21
|
+
end
|
22
|
+
|
23
|
+
def apply_annotations(content)
|
24
|
+
annotation_symbols = []
|
25
|
+
annotation_symbols << '**' if @annotations.bold
|
26
|
+
annotation_symbols << '_' if @annotations.italic
|
27
|
+
annotation_symbols << '`' if @annotations.code
|
28
|
+
wrap_with(content, annotation_symbols)
|
29
|
+
end
|
30
|
+
|
31
|
+
def wrap_with(string, wrappers)
|
32
|
+
"#{wrappers.join}#{string}#{wrappers.reverse.join}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|