Skip to content

Commit

Permalink
Merge pull request #9 from e-alizadeh/master
Browse files Browse the repository at this point in the history
Bugfix for limited  chars limits in Readwise highlights
  • Loading branch information
e-alizadeh authored Jan 3, 2022
2 parents 76584cc + 724f7e5 commit f27bd0c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 18 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ zt_rw = Zotero2Readwise(
)
zt_rw.run()
```
Just to make sure that all files are created, you can run `save_failed_items_to_json()` from `readwise` attribute of
the class object to save any highlight that failed to upload to Readwise.
If a file or more failed to create, the filename (item title) and the corresponding Zotero
item key will be saved to a txt file.
```python
zt_rw.readwise.save_failed_items_to_json("failed_readwise_highlights.json")
```

## Approach 2
You can use the `run.py` script. Run `python run.py -h` to get more information about all options.
Expand Down
5 changes: 5 additions & 0 deletions zotero2readwise/exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Zotero2ReadwiseError(Exception):
def __init__(self, message: str):
self.message = message

super().__init__(self.message)
39 changes: 30 additions & 9 deletions zotero2readwise/readwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import requests

from zotero2readwise import FAILED_ITEMS_DIR
from zotero2readwise.exception import Zotero2ReadwiseError
from zotero2readwise.helper import sanitize_tag
from zotero2readwise.zotero import ZoteroItem

Expand Down Expand Up @@ -57,11 +58,22 @@ def __init__(self, readwise_token: str):
self.failed_highlights: List = []

def create_highlights(self, highlights: List[Dict]) -> None:
requests.post(
resp = requests.post(
url=self.endpoints.highlights,
headers=self._header,
json={"highlights": highlights},
)
if resp.status_code != 200:
error_log_file = (
f"error_log_{resp.status_code}_failed_post_request_to_readwise.json"
)
with open(error_log_file, "w") as f:
dump(resp.json(), f)
raise Zotero2ReadwiseError(
f"Uploading to Readwise failed with following details:\n"
f"POST request Status Code={resp.status_code} ({resp.reason})\n"
f"Error log is saved to {error_log_file} file."
)

@staticmethod
def convert_tags_to_readwise_format(tags: List[str]) -> str:
Expand Down Expand Up @@ -106,29 +118,38 @@ def post_zotero_annotations_to_readwise(
self, zotero_annotations: List[ZoteroItem]
) -> None:
print(
f"Start formatting {len(zotero_annotations)} annotations/notes...\n"
f"\nReadwise: Push {len(zotero_annotations)} Zotero annotations/notes to Readwise...\n"
f"It may take some time depending on the number of highlights...\n"
f"A complete message will show up once it's done!\n"
)
rw_highlights = []
for annot in zotero_annotations:
try:
if len(annot.text) >= 8191:
print(
f"A Zotero annotation from an item with {annot.title} (item_key={annot.key} and "
f"version={annot.version}) cannot be uploaded since the highlight/note is very long. "
f"A Readwise highlight can be up to 8191 characters."
)
self.failed_highlights.append(annot.get_nonempty_params())
continue # Go to next annot
rw_highlight = self.convert_zotero_annotation_to_readwise_highlight(
annot
)
except:
self.failed_highlights.append(annot)
continue
self.failed_highlights.append(annot.get_nonempty_params())
continue # Go to next annot
rw_highlights.append(rw_highlight.get_nonempty_params())

self.create_highlights(rw_highlights)

finished_msg = f"\n{len(rw_highlights)} highlights were successfully uploaded to Readwise.\n"
finished_msg = ""
if self.failed_highlights:
finished_msg += (
f"NOTE: {len(self.failed_highlights)} highlights (out of {len(self.failed_highlights)}) failed.\n"
f"You can run `save_failed_items_to_json()` class method to save those items."
finished_msg = (
f"\nNOTE: {len(self.failed_highlights)} highlights (out of {len(self.failed_highlights)}) failed "
f"to upload to Readwise.\n"
)

finished_msg += f"\n{len(rw_highlights)} highlights were successfully uploaded to Readwise.\n\n"
print(finished_msg)

def save_failed_items_to_json(self, json_filepath_failed_items: str = None):
Expand Down
11 changes: 4 additions & 7 deletions zotero2readwise/zotero.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def format_item(self, annot: Dict) -> ZoteroItem:
def format_items(self, annots: List[Dict]) -> List[ZoteroItem]:
formatted_annots = []
print(
f"Start formatting {len(annots)} annotations/notes...\n"
f"ZOTERO: Start formatting {len(annots)} annotations/notes...\n"
f"It may take some time depending on the number of annotations...\n"
f"A complete message will show up once it's done!\n"
)
Expand All @@ -206,10 +206,10 @@ def format_items(self, annots: List[Dict]) -> List[ZoteroItem]:
self.failed_items.append(annot)
continue

finished_msg = "\nFormatting job is done!!\n"
finished_msg = "\nZOTERO: Formatting Zotero Items is completed!!\n\n"
if self.failed_items:
finished_msg += (
f"NOTE: {len(self.failed_items)} annotations/notes (out of {len(annots)}) failed to format.\n"
f"\nNOTE: {len(self.failed_items)} Zotero annotations/notes (out of {len(annots)}) failed to format.\n"
f"You can run `save_failed_items_to_json()` class method to save those items."
)
print(finished_msg)
Expand All @@ -223,10 +223,7 @@ def save_failed_items_to_json(self, json_filepath_failed_items: str = None):
out_filepath = FAILED_ITEMS_DIR.joinpath("failed_zotero_items.json")
with open(out_filepath, "w") as f:
dump(self.failed_items, f)
print(
f"{len(self.failed_items)} annotations/notes failed to format.\n"
f"Detail of failed items are saved into {out_filepath}"
)
print(f"\nZOTERO: Detail of failed items are saved into {out_filepath}\n")


def retrieve_all_annotations(zotero_client: Zotero) -> List[Dict]:
Expand Down
2 changes: 0 additions & 2 deletions zotero2readwise/zt2rw.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,3 @@ def run(self, zot_annots_notes: List[Dict] = None) -> None:
self.zotero.save_failed_items_to_json("failed_zotero_items.json")

self.readwise.post_zotero_annotations_to_readwise(formatted_items)
if self.readwise.failed_highlights:
self.readwise.save_failed_items_to_json("failed_readwise_highlights.json")

0 comments on commit f27bd0c

Please sign in to comment.