add support for highlights API

This commit is contained in:
stve 2015-02-09 23:47:09 -05:00
parent 775fdf854e
commit 39bc1dc1e7
9 changed files with 199 additions and 2 deletions

View file

@ -0,0 +1,31 @@
require 'faraday'
require 'json'
module Instapaper
module API
module Response
class ParseJson < Faraday::Response::Middleware
WHITESPACE_REGEX = /\A^\s*$\z/
def parse(body)
case body
when WHITESPACE_REGEX, nil
nil
else
JSON.parse(body, :symbolize_names => true)
end
end
def on_complete(response)
response.body = parse(response.body) if respond_to?(:parse) && !unparsable_status_codes.include?(response.status)
end
def unparsable_status_codes
[204, 301, 302, 304]
end
end
end
end
end
Faraday::Response.register_middleware :instapaper_parse_json => Instapaper::API::Response::ParseJson

View file

@ -3,6 +3,7 @@ require 'instapaper/api/bookmark'
require 'instapaper/api/folder'
require 'instapaper/api/highlight'
require 'instapaper/api/oauth'
require 'instapaper/api/utils'
module Instapaper
module API
@ -11,5 +12,6 @@ module Instapaper
include Instapaper::API::Folder
include Instapaper::API::Highlight
include Instapaper::API::OAuth
include Instapaper::API::Utils
end
end

View file

@ -1,7 +1,33 @@
require 'instapaper/highlight'
module Instapaper
module API
# Defines methods related to highlights
module Highlight
# List highlights for a bookmark
def highlights(bookmark_id)
perform_post_with_objects("/api/1.1/bookmarks/#{bookmark_id}/highlights", {}, Instapaper::Highlight)
end
# Create a new highlight
# @note Non-subscribers are limited to 5 highlights per month.
# @param bookmark_id [String, Integer]
# @param options [Hash]
# @option options [String] :text The text for the highlight (HTML tags in text parameter should be unescaped.)
# @option options [String, Integer] :posiiton The 0-indexed position of text in the content. Defaults to 0.
# @return [Instapaper::Highlight]
def highlight(bookmark_id, options = {})
perform_post_with_object("/api/1.1/bookmarks/#{bookmark_id}/highlight", options, Instapaper::Highlight)
end
# Delete a highlight
# @param highlight_id [String, Integer]
# @return [Boolean]
def delete_highlight(highlight_id, options = {})
perform_post_with_empty_response("/api/1.1/highlights/#{highlight_id}/delete", options)
true
end
end
end
end

View file

@ -0,0 +1,46 @@
module Instapaper
module API
module Utils
private
# @param path [String]
# @param options [Hash]
# @param klass [Class]
def perform_post_with_objects(path, options, klass)
perform_request_with_objects(:post, path, options, klass)
end
# @param request_method [Symbol]
# @param path [String]
# @param options [Hash]
# @param klass [Class]
def perform_request_with_objects(request_method, path, options, klass)
perform_request(request_method, path, options).collect do |element|
klass.with(element)
end
end
# @param path [String]
# @param options [Hash]
# @param klass [Class]
def perform_post_with_object(path, options, klass)
perform_request_with_object(:post, path, options, klass)
end
# @param request_method [Symbol]
# @param path [String]
# @param options [Hash]
# @param klass [Class]
def perform_request_with_object(request_method, path, options, klass)
response = perform_request(request_method, path, options)
klass.with(response)
end
# @param path [String]
# @param options [Hash]
def perform_post_with_empty_response(path, options)
perform_request(:post, path, options, true)
end
end
end
end

View file

@ -2,6 +2,7 @@ require 'instapaper/api'
require 'instapaper/error'
require 'instapaper/version'
require 'faraday_middleware'
require 'faraday/response/parse_json'
require 'faraday/response/raise_http_1xxx'
module Instapaper
@ -81,8 +82,8 @@ module Instapaper
end
builder.use Faraday::Request::Multipart
builder.use Faraday::Request::UrlEncoded
builder.use Faraday::Response::Rashify unless raw
builder.use Faraday::Response::ParseJson unless raw
# builder.use Faraday::Response::Rashify unless raw
builder.use Instapaper::API::Response::ParseJson unless raw
builder.use Faraday::Response::RaiseHttp1xxx
builder.adapter(adapter)
end
@ -112,6 +113,7 @@ module Instapaper
end
raw ? response : response.body
end
alias_method :perform_request, :request
# Authentication hash
#

View file

@ -0,0 +1,6 @@
require 'values'
module Instapaper
class Highlight < Value.new(:type, :highlight_id, :bookmark_id, :text, :position, :time)
end
end

8
spec/fixtures/highlight.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"type":"highlight",
"highlight_id":42,
"bookmark_id":123,
"text":"example page",
"position":0,
"time":1394470555
}

18
spec/fixtures/highlights_list.json vendored Normal file
View file

@ -0,0 +1,18 @@
[
{
"type":"highlight",
"highlight_id":42,
"bookmark_id":123,
"text":"example page",
"position":0,
"time":1394470555
},
{
"type":"highlight",
"highlight_id":43,
"bookmark_id":123,
"text":"example page 2",
"position":1,
"time":1394470555
}
]

View file

@ -0,0 +1,58 @@
require 'spec_helper'
describe Instapaper::Client::Highlight do
let(:client) { Instapaper::Client.new(consumer_key: 'CK', consumer_secret: 'CS', oauth_token: 'OT', oauth_token_secret: 'OS') }
describe '#highlights' do
before do
stub_post('/api/1.1/bookmarks/123/highlights')
.to_return(status: 200, body: fixture('highlights_list.json'), headers: {content_type: 'application/json; charset=utf-8'})
end
it 'should get the correct resource' do
client.highlights(123)
expect(a_post('/api/1.1/bookmarks/123/highlights')).to have_been_made
end
it 'should return an array containing folders on success' do
highlights = client.highlights(123)
expect(highlights).to be_an Array
expect(highlights.size).to eq(2)
expect(highlights.first).to be_an Instapaper::Highlight
end
end
describe '#highlight' do
before do
stub_post('/api/1.1/bookmarks/123/highlight')
.to_return(status: 200, body: fixture('highlight.json'), headers: {content_type: 'application/json; charset=utf-8'})
end
it 'should get the correct resource' do
client.highlight(123, text: 'This is the highlighted text.', position: 22)
expect(a_post('/api/1.1/bookmarks/123/highlight')).to have_been_made
end
it 'should return an array containing folders on success' do
highlight = client.highlight(123, text: 'This is the highlighted text.', position: 22)
expect(highlight).to be_an Instapaper::Highlight
end
end
describe '#delete_highlight' do
before do
stub_post('/api/1.1/highlights/123/delete')
.to_return(status: 200, body: '', headers: {content_type: 'application/json; charset=utf-8'})
end
it 'should post to the correct resource' do
client.delete_highlight(123)
expect(a_post('/api/1.1/highlights/123/delete')).to have_been_made
end
it 'should return true when successful' do
response = client.delete_highlight(123)
expect(response).to be true
end
end
end