diff --git a/README.md b/README.md index 9b39a8d..748365c 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/lib/readwise/client.rb b/lib/readwise/client.rb index 21f878a..cb4782c 100644 --- a/lib/readwise/client.rb +++ b/lib/readwise/client.rb @@ -4,6 +4,7 @@ require_relative 'highlight' require_relative 'tag' require_relative 'document' +require_relative 'review' module Readwise class Client @@ -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] @@ -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) diff --git a/lib/readwise/review.rb b/lib/readwise/review.rb new file mode 100644 index 0000000..21644e2 --- /dev/null +++ b/lib/readwise/review.rb @@ -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 \ No newline at end of file diff --git a/spec/fixtures/daily_review.json b/spec/fixtures/daily_review.json new file mode 100644 index 0000000..bf5dd04 --- /dev/null +++ b/spec/fixtures/daily_review.json @@ -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": [] + } + ] +} \ No newline at end of file diff --git a/spec/readwise/client_spec.rb b/spec/readwise/client_spec.rb index 1265c46..def52b6 100644 --- a/spec/readwise/client_spec.rb +++ b/spec/readwise/client_spec.rb @@ -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 @@ -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) } diff --git a/spec/readwise/review_spec.rb b/spec/readwise/review_spec.rb new file mode 100644 index 0000000..a73158b --- /dev/null +++ b/spec/readwise/review_spec.rb @@ -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 \ No newline at end of file