Spaces:
Sleeping
Sleeping
s6bhatti
commited on
Commit
·
e83a653
1
Parent(s):
5db576d
Add page, database, divider, heading, and paragraph functionality
Browse files- .gitignore +2 -0
- blueprints/__init__.py +0 -0
- blueprints/architect.py +24 -0
- blueprints/blocks.py +118 -0
- run.py +26 -0
- sample_data.json +101 -0
.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
.idea
|
2 |
+
blueprints/__pycache__
|
blueprints/__init__.py
ADDED
File without changes
|
blueprints/architect.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .blocks import create_page, create_database, create_divider, create_heading, create_paragraph
|
2 |
+
|
3 |
+
|
4 |
+
def process_blueprint(parent_id, block_json):
|
5 |
+
block_type = block_json["type"]
|
6 |
+
|
7 |
+
if block_type == "page":
|
8 |
+
title = block_json.get("title", "Untitled Page")
|
9 |
+
page_id = create_page(parent_id, title)["id"]
|
10 |
+
for child in block_json.get("children", []):
|
11 |
+
process_blueprint(page_id, child)
|
12 |
+
elif block_type == "database":
|
13 |
+
title = block_json.get("title", "Untitled Database")
|
14 |
+
schema = block_json.get("schema", {})
|
15 |
+
create_database(parent_id, title, schema)
|
16 |
+
elif block_type == "divider":
|
17 |
+
create_divider(parent_id)
|
18 |
+
elif block_type.startswith("heading_"):
|
19 |
+
text = block_json.get("text", "")
|
20 |
+
level = int(block_type.split("_")[1])
|
21 |
+
create_heading(parent_id, text, level)
|
22 |
+
elif block_type == "paragraph":
|
23 |
+
text = block_json.get("text", "")
|
24 |
+
create_paragraph(parent_id, text)
|
blueprints/blocks.py
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from notion_client import Client
|
4 |
+
|
5 |
+
notion = Client(auth=os.environ["NOTION_KEY"])
|
6 |
+
|
7 |
+
|
8 |
+
def create_page(parent_id, title):
|
9 |
+
new_page = notion.pages.create(**{
|
10 |
+
"parent": {
|
11 |
+
"page_id": parent_id
|
12 |
+
},
|
13 |
+
"properties": {
|
14 |
+
"title": {
|
15 |
+
"title": [
|
16 |
+
{
|
17 |
+
"type": "text",
|
18 |
+
"text": {
|
19 |
+
"content": title,
|
20 |
+
},
|
21 |
+
}
|
22 |
+
]
|
23 |
+
},
|
24 |
+
},
|
25 |
+
})
|
26 |
+
return new_page
|
27 |
+
|
28 |
+
|
29 |
+
def create_database(parent_id, title, schema):
|
30 |
+
approved_types = (
|
31 |
+
"title", "rich_text", "number", "checkbox", "date", "people",
|
32 |
+
"files", "url", "email", "phone_number", "select", "multi_select"
|
33 |
+
)
|
34 |
+
|
35 |
+
properties = {}
|
36 |
+
for name, info in schema.items():
|
37 |
+
prop_type = info["type"]
|
38 |
+
if prop_type not in approved_types:
|
39 |
+
raise ValueError(f"Property type '{prop_type}' is currently unsupported.")
|
40 |
+
|
41 |
+
if prop_type in ["select", "multi_select"]:
|
42 |
+
properties[name] = {prop_type: {"options": info["options"]}}
|
43 |
+
else:
|
44 |
+
properties[name] = {prop_type: {}}
|
45 |
+
|
46 |
+
new_database = notion.databases.create(**{
|
47 |
+
"parent": {"page_id": parent_id},
|
48 |
+
"title": [
|
49 |
+
{
|
50 |
+
"type": "text",
|
51 |
+
"text": {
|
52 |
+
"content": title
|
53 |
+
}
|
54 |
+
}
|
55 |
+
],
|
56 |
+
"properties": properties
|
57 |
+
})
|
58 |
+
return new_database
|
59 |
+
|
60 |
+
|
61 |
+
def create_divider(parent_id):
|
62 |
+
divider_block = notion.blocks.children.append(**{
|
63 |
+
"block_id": parent_id,
|
64 |
+
"children": [
|
65 |
+
{
|
66 |
+
"object": "block",
|
67 |
+
"type": "divider",
|
68 |
+
"divider": {},
|
69 |
+
}
|
70 |
+
]
|
71 |
+
})
|
72 |
+
return divider_block
|
73 |
+
|
74 |
+
|
75 |
+
def create_heading(parent_id, text, level):
|
76 |
+
heading_block = notion.blocks.children.append(**{
|
77 |
+
"block_id": parent_id,
|
78 |
+
"children": [
|
79 |
+
{
|
80 |
+
"object": "block",
|
81 |
+
"type": f"heading_{level}",
|
82 |
+
f"heading_{level}": {
|
83 |
+
"rich_text": [
|
84 |
+
{
|
85 |
+
"type": "text",
|
86 |
+
"text": {
|
87 |
+
"content": text
|
88 |
+
}
|
89 |
+
}
|
90 |
+
],
|
91 |
+
},
|
92 |
+
}
|
93 |
+
]
|
94 |
+
})
|
95 |
+
return heading_block
|
96 |
+
|
97 |
+
|
98 |
+
def create_paragraph(parent_id, text):
|
99 |
+
paragraph_block = notion.blocks.children.append(**{
|
100 |
+
"block_id": parent_id,
|
101 |
+
"children": [
|
102 |
+
{
|
103 |
+
"object": "block",
|
104 |
+
"type": "paragraph",
|
105 |
+
"paragraph": {
|
106 |
+
"rich_text": [
|
107 |
+
{
|
108 |
+
"type": "text",
|
109 |
+
"text": {
|
110 |
+
"content": text
|
111 |
+
}
|
112 |
+
}
|
113 |
+
],
|
114 |
+
},
|
115 |
+
}
|
116 |
+
]
|
117 |
+
})
|
118 |
+
return paragraph_block
|
run.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import argparse
|
2 |
+
import json
|
3 |
+
import os
|
4 |
+
|
5 |
+
from blueprints.architect import process_blueprint
|
6 |
+
|
7 |
+
|
8 |
+
def load_blueprint(filename):
|
9 |
+
with open(filename, "r") as file:
|
10 |
+
return json.load(file)
|
11 |
+
|
12 |
+
|
13 |
+
def main():
|
14 |
+
parser = argparse.ArgumentParser(description="Process a JSON blueprint to create content in Notion.")
|
15 |
+
parser.add_argument("json_file", help="Location of the JSON blueprint file")
|
16 |
+
args = parser.parse_args()
|
17 |
+
|
18 |
+
notion_page_id = os.environ["NOTION_PAGE_ID"]
|
19 |
+
|
20 |
+
blueprint = load_blueprint(args.json_file)
|
21 |
+
process_blueprint(notion_page_id, blueprint)
|
22 |
+
|
23 |
+
|
24 |
+
if __name__ == "__main__":
|
25 |
+
main()
|
26 |
+
|
sample_data.json
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"type": "page",
|
3 |
+
"title": "Weekly Grocery Planning",
|
4 |
+
"children": [
|
5 |
+
{
|
6 |
+
"type": "heading_1",
|
7 |
+
"text": "Grocery List Overview"
|
8 |
+
},
|
9 |
+
{
|
10 |
+
"type": "paragraph",
|
11 |
+
"text": "Organize your weekly grocery shopping with a detailed list and budget tracking."
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"type": "database",
|
15 |
+
"title": "Grocery List",
|
16 |
+
"schema": {
|
17 |
+
"Name": {
|
18 |
+
"type": "title"
|
19 |
+
},
|
20 |
+
"Description": {
|
21 |
+
"type": "rich_text"
|
22 |
+
},
|
23 |
+
"In stock": {
|
24 |
+
"type": "checkbox"
|
25 |
+
},
|
26 |
+
"Food group": {
|
27 |
+
"type": "select",
|
28 |
+
"options": [
|
29 |
+
{
|
30 |
+
"name": "🥦Vegetable",
|
31 |
+
"color": "green"
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"name": "🍎Fruit",
|
35 |
+
"color": "red"
|
36 |
+
},
|
37 |
+
{
|
38 |
+
"name": "💪Protein",
|
39 |
+
"color": "yellow"
|
40 |
+
}
|
41 |
+
]
|
42 |
+
},
|
43 |
+
"Price": {
|
44 |
+
"type": "number",
|
45 |
+
"format": "dollar"
|
46 |
+
},
|
47 |
+
"Last ordered": {
|
48 |
+
"type": "date"
|
49 |
+
},
|
50 |
+
"Store availability": {
|
51 |
+
"type": "multi_select",
|
52 |
+
"options": [
|
53 |
+
{
|
54 |
+
"name": "Duc Loi Market",
|
55 |
+
"color": "blue"
|
56 |
+
},
|
57 |
+
{
|
58 |
+
"name": "Rainbow Grocery",
|
59 |
+
"color": "gray"
|
60 |
+
},
|
61 |
+
{
|
62 |
+
"name": "Nijiya Market",
|
63 |
+
"color": "purple"
|
64 |
+
},
|
65 |
+
{
|
66 |
+
"name": "Gus's Community Market",
|
67 |
+
"color": "yellow"
|
68 |
+
}
|
69 |
+
]
|
70 |
+
},
|
71 |
+
"+1": {
|
72 |
+
"type": "people"
|
73 |
+
},
|
74 |
+
"Photo": {
|
75 |
+
"type": "files"
|
76 |
+
}
|
77 |
+
}
|
78 |
+
},
|
79 |
+
{
|
80 |
+
"type": "divider"
|
81 |
+
},
|
82 |
+
{
|
83 |
+
"type": "heading_2",
|
84 |
+
"text": "Shopping Tips"
|
85 |
+
},
|
86 |
+
{
|
87 |
+
"type": "paragraph",
|
88 |
+
"text": "Consider seasonal produce for fresher options and better prices. Don't forget to check pantry staples before heading out."
|
89 |
+
},
|
90 |
+
{
|
91 |
+
"type": "page",
|
92 |
+
"title": "Favorite Recipes",
|
93 |
+
"children": [
|
94 |
+
{
|
95 |
+
"type": "paragraph",
|
96 |
+
"text": "Compile your go-to recipes here for quick access while planning meals."
|
97 |
+
}
|
98 |
+
]
|
99 |
+
}
|
100 |
+
]
|
101 |
+
}
|