Skip to content

Commit

Permalink
feat(readwise): add support for adding tags to the highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
bskim45 committed Sep 8, 2024
1 parent cbed9c2 commit d69eec3
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 10 deletions.
67 changes: 59 additions & 8 deletions src/ridiwise/api/readwise.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import json
from typing import Optional, TypedDict
from typing import Literal, Optional, TypedDict

import httpx

from ridiwise.api.base_client import BaseClient, HTTPTokenAuth

# https://readwise.io/api_deets
API_BASE_URL = 'https://readwise.io/api/v2'


class CreateHighlight(TypedDict, total=False):
type BookCategory = Literal['books', 'articles', 'tweets', 'podcasts']
type HightlightLocationType = Literal['page', 'order', 'time_offset']


class CreateHighlightRequestItem(TypedDict, total=False):
text: str
title: str
author: Optional[str]
category: Optional[str]
location: Optional[str]
location_type: Optional[str]
category: Optional[BookCategory]
location: Optional[int]
location_type: Optional[HightlightLocationType]
highlighted_at: Optional[str]
source_url: Optional[str]
source_type: Optional[str]
Expand All @@ -23,6 +28,37 @@ class CreateHighlight(TypedDict, total=False):
highlight_url: Optional[str]


class CreateHighlightsRequest(TypedDict):
highlights: list[CreateHighlightRequestItem]


class CreateHighlightResponseItem(TypedDict):
id: int
title: Optional[str]
author: Optional[str]
category: Optional[BookCategory]
source: Optional[str]
num_highlights: int
last_highlight_at: Optional[str]
updated: str
cover_image_url: Optional[str]
highlights_url: Optional[str]
source_url: Optional[str]
modified_highlights: list[int]


type CreateHighlightsResponse = list[CreateHighlightResponseItem]


class CreateHighlightTagRequest(TypedDict):
name: str


class CreateHighlightTagResponse(TypedDict):
id: int
name: str


class ReadwiseClient(BaseClient):
base_url = API_BASE_URL
provider = 'readwise'
Expand All @@ -48,12 +84,27 @@ def validate_token(self):

def create_highlights(
self,
highlights: list[CreateHighlight],
):
payload = {'highlights': highlights}
highlights: list[CreateHighlightRequestItem],
) -> CreateHighlightsResponse:
payload: CreateHighlightsRequest = {'highlights': highlights}

self.logger.debug(json.dumps(payload, indent=2, ensure_ascii=False))

response = self.client.post('/highlights/', auth=self.auth, json=payload)
response.raise_for_status()
return response.json()

def create_highlight_tag(
self,
highlight_id: int,
tag: str,
) -> CreateHighlightTagResponse:
payload: CreateHighlightTagRequest = {'name': tag}

response = self.client.post(
f'/highlights/{highlight_id}/tags/',
auth=self.auth,
json=payload,
)
response.raise_for_status()
return response.json()
23 changes: 21 additions & 2 deletions src/ridiwise/cmd/sync/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

import typer
from typing_extensions import Annotated

Expand Down Expand Up @@ -28,6 +30,12 @@ def readwise(
help='Readwise.io API token. https://readwise.io/access_token',
),
],
tags: Annotated[
Optional[list[str]],
typer.Option(
help='Tags to attach to the highlights. Multiple tags can be provided.',
),
] = None,
):
"""
Sync Ridibooks book notes to Readwise.io.
Expand All @@ -54,7 +62,7 @@ def readwise(
}

for book in books:
readwise_client.create_highlights(
highlights_response = readwise_client.create_highlights(
highlights=[
{
'text': note['highlighted_text'],
Expand All @@ -65,13 +73,24 @@ def readwise(
'highlighted_at': note['created_date'].isoformat(),
'note': note['memo'],
'source_url': book['book_url'],
'highlight_url': f'{book["book_notes_url"]}#annotation_{note["id"]}', # noqa: E501 pylint: disable=line-too-long
'highlight_url': (
f'{book["book_notes_url"]}#annotation_{note["id"]}'
),
'image_url': book['book_cover_image_url'],
}
for note in book['notes']
]
)

modified_highlight_ids = highlights_response[0]['modified_highlights']

if tags:
for highlight_id, tag in zip(modified_highlight_ids, tags):
readwise_client.create_highlight_tag(
highlight_id=highlight_id,
tag=tag,
)

result_count['books'] += 1
result_count['highlights'] += len(book['notes'])

Expand Down

0 comments on commit d69eec3

Please sign in to comment.