1212from typing import TYPE_CHECKING , Any
1313from urllib .parse import urlparse
1414from urllib .request import url2pathname
15- from uuid import UUID
1615
1716import click
17+ import requests
1818from beartype import beartype
19- from ultimate_notion import Emoji , Session
19+ from ultimate_notion import Emoji , NotionFile , Session
2020from ultimate_notion .blocks import PDF as UnoPDF # noqa: N811
2121from ultimate_notion .blocks import Audio as UnoAudio
2222from ultimate_notion .blocks import Block
@@ -45,6 +45,21 @@ def _calculate_file_sha(*, file_path: Path) -> str:
4545 return sha256_hash .hexdigest ()
4646
4747
48+ @beartype
49+ @cache
50+ def _calculate_file_sha_from_url (* , file_url : str ) -> str :
51+ """
52+ Calculate SHA-256 hash of a file from a URL.
53+ """
54+ sha256_hash = hashlib .sha256 ()
55+ with requests .get (url = file_url , stream = True , timeout = 10 ) as response :
56+ response .raise_for_status ()
57+ for chunk in response .iter_content (chunk_size = 4096 ):
58+ if chunk :
59+ sha256_hash .update (chunk )
60+ return sha256_hash .hexdigest ()
61+
62+
4863@beartype
4964def _find_last_matching_block_index (
5065 * ,
@@ -58,6 +73,12 @@ def _find_last_matching_block_index(
5873 """
5974 last_matching_index : int | None = None
6075 for index , existing_page_block in enumerate (iterable = existing_blocks ):
76+ click .echo (
77+ message = (
78+ f"Checking block { index + 1 } of { len (existing_blocks )} for "
79+ "equivalence"
80+ ),
81+ )
6182 if index < len (local_blocks ) and (
6283 _is_existing_equivalent (
6384 existing_page_block = existing_page_block ,
@@ -75,31 +96,41 @@ def _is_existing_equivalent(
7596 * ,
7697 existing_page_block : Block ,
7798 local_block : Block ,
78- sha_to_block_id : dict [str , str ],
7999) -> bool :
80100 """
81101 Check if a local block is equivalent to an existing page block.
82102 """
83- if existing_page_block == local_block :
84- return True
103+ if type ( existing_page_block ) is not type ( local_block ) :
104+ return False
85105
86106 if isinstance (local_block , _FILE_BLOCK_TYPES ):
87107 parsed = urlparse (url = local_block .url )
88108 if parsed .scheme == "file" :
89- file_path = Path (url2pathname (parsed .path )) # type: ignore[misc]
90- file_sha = _calculate_file_sha (file_path = file_path )
91- existing_page_block_id_with_file_sha = sha_to_block_id .get (
92- file_sha
93- )
94- if not existing_page_block_id_with_file_sha :
109+ assert isinstance (existing_page_block , _FILE_BLOCK_TYPES )
110+ if not isinstance (existing_page_block .file_info , NotionFile ):
95111 return False
112+
96113 if (
97- UUID ( hex = existing_page_block_id_with_file_sha )
98- == existing_page_block . id
114+ existing_page_block . file_info . name
115+ != local_block . file_info . name
99116 ):
117+ return False
118+
119+ if (
120+ existing_page_block .file_info .caption
121+ != local_block .file_info .caption
122+ ):
123+ return False
124+
125+ local_file_path = Path (url2pathname (parsed .path )) # type: ignore[misc]
126+ local_file_sha = _calculate_file_sha (file_path = local_file_path )
127+ existing_file_sha = _calculate_file_sha_from_url (
128+ file_url = existing_page_block .file_info .url ,
129+ )
130+ if local_file_sha != existing_file_sha :
100131 return True
101132
102- return False
133+ return existing_page_block == local_block
103134
104135
105136@beartype
0 commit comments