Skip to content

Commit 9a9054c

Browse files
committed
Handle uploaded images
1 parent 9f970ff commit 9a9054c

File tree

3 files changed

+87
-22
lines changed

3 files changed

+87
-22
lines changed

src/backend/core/api/viewsets.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,13 +2111,33 @@ def notion_import_callback(request):
21112111
return redirect(f"{settings.FRONTEND_URL}/import-notion/")
21122112

21132113

2114-
def _import_notion_child_page(imported_doc, parent_doc, user, imported_docs_by_page_id):
2115-
document_content = YdocConverter().convert_blocks(imported_doc.blocks)
2114+
def _import_notion_doc_content(imported_doc, obj, user):
2115+
for att in imported_doc.attachments:
2116+
extra_args = {
2117+
"Metadata": {
2118+
"owner": str(user.id),
2119+
"status": enums.DocumentAttachmentStatus.READY, # TODO
2120+
},
2121+
}
2122+
file_id = uuid.uuid4()
2123+
key = f"{obj.key_base}/{enums.ATTACHMENTS_FOLDER:s}/{file_id!s}.raw"
2124+
with requests.get(att.file.file["url"], stream=True) as resp:
2125+
default_storage.connection.meta.client.upload_fileobj(
2126+
resp.raw, default_storage.bucket_name, key
2127+
)
2128+
obj.attachments.append(key)
2129+
att.block["props"]["url"] = (
2130+
f"{settings.MEDIA_BASE_URL}{settings.MEDIA_URL}{key}"
2131+
)
2132+
2133+
obj.content = YdocConverter().convert_blocks(imported_doc.blocks)
2134+
obj.save()
21162135

2136+
2137+
def _import_notion_child_page(imported_doc, parent_doc, user, imported_docs_by_page_id):
21172138
obj = parent_doc.add_child(
21182139
creator=user,
21192140
title=imported_doc.page.get_title() or "J'aime les carottes",
2120-
content=document_content,
21212141
)
21222142

21232143
models.DocumentAccess.objects.create(
@@ -2126,21 +2146,20 @@ def _import_notion_child_page(imported_doc, parent_doc, user, imported_docs_by_p
21262146
role=models.RoleChoices.OWNER,
21272147
)
21282148

2149+
_import_notion_doc_content(imported_doc, obj, user)
2150+
21292151
imported_docs_by_page_id[imported_doc.page.id] = obj
21302152

21312153
for child in imported_doc.children:
21322154
_import_notion_child_page(child, obj, user, imported_docs_by_page_id)
21332155

21342156

21352157
def _import_notion_root_page(imported_doc, user, imported_docs_by_page_id):
2136-
document_content = YdocConverter().convert_blocks(imported_doc.blocks)
2137-
21382158
obj = models.Document.add_root(
21392159
depth=1,
21402160
creator=user,
21412161
title=imported_doc.page.get_title() or "J'aime les courgettes",
21422162
link_reach=models.LinkReachChoices.RESTRICTED,
2143-
content=document_content,
21442163
)
21452164

21462165
models.DocumentAccess.objects.create(
@@ -2149,13 +2168,15 @@ def _import_notion_root_page(imported_doc, user, imported_docs_by_page_id):
21492168
role=models.RoleChoices.OWNER,
21502169
)
21512170

2171+
_import_notion_doc_content(imported_doc, obj, user)
2172+
21522173
imported_docs_by_page_id[imported_doc.page.id] = obj
21532174

21542175
for child in imported_doc.children:
21552176
_import_notion_child_page(child, obj, user, imported_docs_by_page_id)
21562177

21572178

2158-
@drf.decorators.api_view(["POST"])
2179+
@drf.decorators.api_view(["GET", "POST"]) # TODO: drop GET (used for testing)
21592180
def notion_import_run(request):
21602181
if "notion_token" not in request.session:
21612182
raise drf.exceptions.PermissionDenied()

src/backend/core/notion_schemas/notion_block.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,12 @@ class NotionEmbed(BaseModel):
166166
url: str
167167

168168

169-
class NotionFileType(StrEnum):
170-
FILE = "file"
171-
EXTERNAL = "external"
172-
FILE_UPLOAD = "file_upload"
173-
174-
175-
class NotionFile(BaseModel):
169+
class NotionBlockFile(BaseModel):
176170
# FIXME: this is actually another occurrence of type discriminating
177171
"""https://developers.notion.com/reference/block#file"""
178172

179173
block_type: Literal[NotionBlockType.FILE] = NotionBlockType.FILE
180-
caption: list[NotionRichText]
181-
type: NotionFileType
182-
...
174+
# TODO: NotionFile
183175

184176

185177
class NotionImage(BaseModel):
@@ -188,6 +180,13 @@ class NotionImage(BaseModel):
188180
block_type: Literal[NotionBlockType.IMAGE] = NotionBlockType.IMAGE
189181
file: NotionFile
190182

183+
@model_validator(mode="before")
184+
@classmethod
185+
def move_file_type_inward_and_rename(cls, data: Any) -> Any:
186+
if not isinstance(data, dict):
187+
return data
188+
return {"block_type": "image", "file": data}
189+
191190

192191
class NotionVideo(BaseModel):
193192
"""https://developers.notion.com/reference/block#video"""
@@ -280,7 +279,7 @@ def put_all_in_raw(cls, data: Any) -> Any:
280279
| NotionColumnList
281280
| NotionDivider
282281
| NotionEmbed
283-
| NotionFile
282+
| NotionBlockFile
284283
| NotionImage
285284
| NotionVideo
286285
| NotionLinkPreview

src/backend/core/services/notion_import.py

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
NotionHeading1,
1919
NotionHeading2,
2020
NotionHeading3,
21+
NotionImage,
2122
NotionNumberedListItem,
2223
NotionParagraph,
2324
NotionTable,
2425
NotionTableRow,
2526
NotionToDo,
2627
NotionUnsupported,
2728
)
29+
from ..notion_schemas.notion_file import NotionFileExternal, NotionFileHosted
2830
from ..notion_schemas.notion_page import (
2931
NotionPage,
3032
NotionParentBlock,
@@ -152,7 +154,42 @@ def convert_rich_text(rich_text: NotionRichText) -> dict[str, Any]:
152154
}
153155

154156

155-
def convert_block(block: NotionBlock) -> list[dict[str, Any]]:
157+
class ImportedAttachment(BaseModel):
158+
block: Any
159+
file: NotionFileHosted
160+
161+
162+
def convert_image(
163+
image: NotionImage, attachments: list[ImportedAttachment]
164+
) -> list[dict[str, Any]]:
165+
# TODO: NotionFileUpload
166+
match image.file:
167+
case NotionFileExternal():
168+
return [
169+
{
170+
"type": "image",
171+
"props": {
172+
"url": image.file.external["url"],
173+
},
174+
}
175+
]
176+
case NotionFileHosted():
177+
block = {
178+
"type": "image",
179+
"props": {
180+
"url": "about:blank", # populated later on
181+
},
182+
}
183+
attachments.append(ImportedAttachment(block=block, file=image.file))
184+
185+
return [block]
186+
case _:
187+
return [{"paragraph": {"content": "Unsupported image type"}}]
188+
189+
190+
def convert_block(
191+
block: NotionBlock, attachments: list[ImportedAttachment]
192+
) -> list[dict[str, Any]]:
156193
match block.specific:
157194
case NotionColumnList():
158195
columns_content = []
@@ -173,6 +210,8 @@ def convert_block(block: NotionBlock) -> list[dict[str, Any]]:
173210
"content": content,
174211
}
175212
]
213+
case NotionImage():
214+
return convert_image(block.specific, attachments)
176215
case NotionHeading1() | NotionHeading2() | NotionHeading3():
177216
return [
178217
{
@@ -335,17 +374,20 @@ def convert_annotations(annotations: NotionRichTextAnnotation) -> dict[str, str]
335374
return res
336375

337376

338-
def convert_block_list(blocks: list[NotionBlock]) -> list[dict[str, Any]]:
377+
def convert_block_list(
378+
blocks: list[NotionBlock], attachments: list[ImportedAttachment]
379+
) -> list[dict[str, Any]]:
339380
converted_blocks = []
340381
for block in blocks:
341-
converted_blocks.extend(convert_block(block))
382+
converted_blocks.extend(convert_block(block, attachments))
342383
return converted_blocks
343384

344385

345386
class ImportedDocument(BaseModel):
346387
page: NotionPage
347388
blocks: list[dict[str, Any]] = []
348389
children: list["ImportedDocument"] = []
390+
attachments: list[ImportedAttachment] = []
349391

350392

351393
def find_block_child_page(block_id: str, all_pages: list[NotionPage]):
@@ -393,10 +435,13 @@ def import_page(
393435
blocks = fetch_block_children(session, page.id)
394436
logger.info(f"Page {page.get_title()} (id {page.id})")
395437
logger.info(blocks)
438+
attachments = []
439+
converted_blocks = convert_block_list(blocks, attachments)
396440
return ImportedDocument(
397441
page=page,
398-
blocks=convert_block_list(blocks),
442+
blocks=converted_blocks,
399443
children=convert_child_pages(session, page, blocks, all_pages),
444+
attachments=attachments,
400445
)
401446

402447

0 commit comments

Comments
 (0)