Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ updated_tag = client.update_highlight_tag(highlight: highlight, tag: added_tag)

# remove a tag from a highlight
client.remove_highlight_tag(highlight: highlight, tag: added_tag)

# get daily review highlights
daily_review = client.daily_review
puts daily_review.id
puts daily_review.url
puts daily_review.completed?
puts daily_review.highlights.size
puts daily_review.highlights.first.text
```

### Reader API (V3)
Expand Down
19 changes: 19 additions & 0 deletions lib/readwise/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative 'highlight'
require_relative 'tag'
require_relative 'document'
require_relative 'review'

module Readwise
class Client
Expand Down Expand Up @@ -126,6 +127,13 @@ def get_book(book_id:)
transform_book(res)
end

def daily_review
url = BASE_URL + 'review/'

res = get_readwise_request(url)
transform_review(res)
end

def export(updated_after: nil, book_ids: [])
resp = export_page(updated_after: updated_after, book_ids: book_ids)
next_page_cursor = resp[:next_page_cursor]
Expand Down Expand Up @@ -275,6 +283,17 @@ def transform_tag(res)
)
end

def transform_review(res)
highlights = (res['highlights'] || []).map { |highlight| transform_highlight(highlight) }

Review.new(
id: res['review_id'],
url: res['review_url'],
completed: res['review_completed'],
highlights: highlights
)
end

def get_readwise_request(url)
uri = URI.parse(url)
req = Net::HTTP::Get.new(uri)
Expand Down
17 changes: 17 additions & 0 deletions lib/readwise/review.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Readwise
Review = Struct.new(
:id,
:url,
:completed,
:highlights,
keyword_init: true
) do
def completed?
completed
end

def serialize
to_h.compact
end
end
end
45 changes: 45 additions & 0 deletions spec/fixtures/daily_review.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"review_id": 12345,
"review_url": "https://readwise.io/review/12345",
"review_completed": false,
"highlights": [
{
"id": 123,
"text": "This is the first highlight for daily review.",
"book_id": 456,
"url": "https://readwise.io/highlight/123",
"highlighted_at": "2023-01-15T10:30:00.000Z",
"created_at": "2023-01-15T10:30:00.000Z",
"updated_at": "2023-01-15T10:30:00.000Z",
"color": "yellow",
"end_location": null,
"external_id": null,
"is_discard": false,
"is_favorite": true,
"location": 1,
"location_type": "page",
"note": null,
"readwise_url": "https://readwise.io/highlight/123",
"tags": []
},
{
"id": 124,
"text": "This is the second highlight for daily review.",
"book_id": 457,
"url": "https://readwise.io/highlight/124",
"highlighted_at": "2023-01-16T14:20:00.000Z",
"created_at": "2023-01-16T14:20:00.000Z",
"updated_at": "2023-01-16T14:20:00.000Z",
"color": "blue",
"end_location": null,
"external_id": null,
"is_discard": false,
"is_favorite": false,
"location": 5,
"location_type": "page",
"note": "This is a note on the highlight",
"readwise_url": "https://readwise.io/highlight/124",
"tags": []
}
]
}
18 changes: 18 additions & 0 deletions spec/readwise/client_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'readwise/client'
require 'readwise/highlight'
require 'readwise/document'
require 'readwise/review'
require "rspec/file_fixtures"

RSpec.describe Readwise::Client do
Expand Down Expand Up @@ -101,6 +102,23 @@
end
end

context 'daily review' do
let(:daily_review_response) { fixture('daily_review.json').from_json(false) }

it 'can retrieve daily review' do
expect(subject).to receive(:get_readwise_request).and_return(daily_review_response)

review = subject.daily_review
expect(review).to be_instance_of Readwise::Review
expect(review.id).to eq(12345)
expect(review.url).to eq('https://readwise.io/review/12345')
expect(review.completed?).to be false
expect(review.highlights).to be_an(Array)
expect(review.highlights.size).to eq(2)
expect(review.highlights.first).to be_instance_of Readwise::Highlight
end
end

context 'documents (V3 API)' do
context 'creating a document' do
let(:document_create_response) { fixture('document_create.json').from_json(false) }
Expand Down
56 changes: 56 additions & 0 deletions spec/readwise/review_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'readwise/review'
require 'readwise/highlight'

RSpec.describe Readwise::Review do
let(:review_data) do
{
id: 12345,
url: 'https://readwise.io/review/12345',
completed: false,
highlights: []
}
end

subject { described_class.new(**review_data) }

describe '#completed?' do
it 'returns false when completed is false' do
expect(subject.completed?).to be false
end

it 'returns true when completed is true' do
review = described_class.new(**review_data.merge(completed: true))
expect(review.completed?).to be true
end
end

describe '#serialize' do
it 'returns a hash representation' do
result = subject.serialize
expect(result).to be_a(Hash)
expect(result[:id]).to eq(12345)
expect(result[:url]).to eq('https://readwise.io/review/12345')
expect(result[:completed]).to be false
end

it 'excludes nil values from serialization' do
review = described_class.new(id: 123, url: 'https://example.com', completed: nil, highlights: [])
result = review.serialize
expect(result).not_to have_key(:completed)
expect(result[:id]).to eq(123)
end
end

describe 'with highlights' do
let(:highlight) { Readwise::Highlight.new(text: 'Sample highlight', highlight_id: '123', book_id: '456', tags: []) }
let(:review_with_highlights) do
described_class.new(**review_data.merge(highlights: [highlight]))
end

it 'stores highlights properly' do
expect(review_with_highlights.highlights).to be_an(Array)
expect(review_with_highlights.highlights.size).to eq(1)
expect(review_with_highlights.highlights.first).to be_instance_of Readwise::Highlight
end
end
end