instapaper 1.0.0.pre3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b394bf891476b148b96540e672a0802158338390
4
- data.tar.gz: b397e12efbfe0eeb28e579d66fea4ccc0b4ad549
3
+ metadata.gz: 9d5a373c9cb9c47ef7fcadc1b9608974f9710756
4
+ data.tar.gz: d3f197b58e0cd8a74f69bf6644333d0071a76220
5
5
  SHA512:
6
- metadata.gz: 08564a692be926e773019744589923d8359ce098701d172fd8f77a69604c11f2920a673a3e920f363839a2264704118ca23fe16fff41b3c1ac3047c942ec62e0
7
- data.tar.gz: e67be46762dbf22c8d0e3b492aaf8e02abc45d7683cfd7d11d795c975dffe5b1d627044180520b7f90ff1592c1c9092c5611041240c705d7c2669ab6bbecf182
6
+ metadata.gz: c1cb814139e10f430465001d096a71e48c4b94f5da15f5ea960c80647c4a67e6946d8bd219b4a7c0acd01a5fff0462a9467fe628c49b90694f6e13710a47d8ce
7
+ data.tar.gz: 716df4e63310adf3a2dba476cfd75e66d31ed42483cd9441fdb59beb583af65527138d927f123b2f7a31f43fca4a9991c98ba70133dfe9fd42af6cca5abe2f45
data/README.md CHANGED
@@ -1,7 +1,14 @@
1
- # Instapaper [![Build Status](https://secure.travis-ci.org/stve/instapaper.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/stve/instapaper.png?travis)][gemnasium]
1
+ # Instapaper
2
2
 
3
- [travis]: http://travis-ci.org/stve/instapaper
3
+ [![Gem Version](http://img.shields.io/gem/v/instapaper.svg)][gem]
4
+ [![Build Status](http://img.shields.io/travis/stve/instapaper.svg)][travis]
5
+ [![Dependency Status](http://img.shields.io/gemnasium/stve/instapaper.svg)][gemnasium]
6
+ [![Code Climate](http://img.shields.io/codeclimate/github/stve/instapaper.svg)][codeclimate]
7
+
8
+ [gem]: https://rubygems.org/gems/instapaper
9
+ [travis]: https://travis-ci.org/stve/instapaper
4
10
  [gemnasium]: https://gemnasium.com/stve/instapaper
11
+ [codeclimate]: https://codeclimate.com/github/stve/instapaper
5
12
 
6
13
 
7
14
  Instapaper is a ruby wrapper for interacting with [Instapaper's Full API](https://www.instapaper.com/api/full). Note that access to the Full API is restricted to Instapaper subscribers only.
@@ -4,7 +4,7 @@ require 'instapaper/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.add_dependency 'addressable', '~> 2.3'
7
- spec.add_dependency 'http', '~> 1.0'
7
+ spec.add_dependency 'http', '~> 2'
8
8
  spec.add_dependency 'multi_json', '~> 1'
9
9
  spec.add_dependency 'simple_oauth', '~> 0.3'
10
10
  spec.add_dependency 'virtus', '~> 1'
@@ -9,7 +9,7 @@ module Instapaper
9
9
  def access_token(username, password)
10
10
  response = perform_post_with_unparsed_response('/api/1.1/oauth/access_token', x_auth_username: username, x_auth_password: password, x_auth_mode: 'client_auth')
11
11
  parsed_response = QLineParser.parse(response)
12
- fail Instapaper::Error::OAuthError, parsed_response['error'] if parsed_response.key?('error')
12
+ raise Instapaper::Error::OAuthError, parsed_response['error'] if parsed_response.key?('error')
13
13
  Instapaper::Credentials.new(parsed_response)
14
14
  end
15
15
  end
@@ -4,14 +4,32 @@ module Instapaper
4
4
  # @return [Integer]
5
5
  attr_reader :code
6
6
 
7
+ ClientError = Class.new(self)
8
+ ServerError = Class.new(self)
7
9
  ServiceUnavailableError = Class.new(self)
8
10
  BookmarkError = Class.new(self)
9
11
  FolderError = Class.new(self)
10
12
  HighlightError = Class.new(self)
11
13
  OAuthError = Class.new(self)
12
14
 
13
- ERRORS = {
14
- 401 => 'Unauthorized',
15
+ CLIENT_ERRORS = {
16
+ 400 => 'Bad Request',
17
+ 401 => 'Unauthorized',
18
+ 402 => 'Payment Required',
19
+ 403 => 'Forbidden',
20
+ 404 => 'Not Found',
21
+ 405 => 'Method Not Allowed',
22
+ }
23
+
24
+ SERVER_ERRORS = {
25
+ 500 => 'Internal Server Error',
26
+ 501 => 'Not Implemented',
27
+ 502 => 'Bad Gateway',
28
+ 503 => 'Service Unavailable',
29
+ 504 => 'Gateway Timeout',
30
+ }
31
+
32
+ SERVICE_ERRORS = {
15
33
  1040 => 'Rate-limit exceeded',
16
34
  1041 => 'Premium account required',
17
35
  1042 => 'Application is suspended',
@@ -43,29 +61,47 @@ module Instapaper
43
61
  }
44
62
 
45
63
  CODES = [
46
- ERRORS,
64
+ CLIENT_ERRORS,
65
+ SERVER_ERRORS,
66
+ SERVICE_ERRORS,
47
67
  BOOKMARK_ERRORS,
48
68
  FOLDER_ERRORS,
49
69
  HIGHLIGHT_ERRORS,
50
70
  ].collect(&:keys).flatten
51
71
 
72
+ HTTP_ERRORS = CLIENT_ERRORS.merge(SERVER_ERRORS)
73
+
52
74
  # Create a new error from an HTTP response
53
75
  #
54
76
  # @param response [HTTP::Response]
55
77
  # @return [Instapaper::Error]
56
78
  def self.from_response(code, path)
57
- if ERRORS.keys.include?(code)
58
- new(ERRORS[code], code)
79
+ if (HTTP_ERRORS.keys + SERVICE_ERRORS.keys).include?(code)
80
+ from_response_code(code)
59
81
  else
60
82
  case path
61
83
  when /highlights/ then HighlightError.new(HIGHLIGHT_ERRORS[code], code)
62
84
  when /bookmarks/ then BookmarkError.new(BOOKMARK_ERRORS[code], code)
63
85
  when /folders/ then FolderError.new(FOLDER_ERRORS[code], code)
64
- else new('Unknown Error Code', code)
86
+ else new('Unknown Error', code)
65
87
  end
66
88
  end
67
89
  end
68
90
 
91
+ # Create a new error from an HTTP response code
92
+ #
93
+ # @param code [Integer]
94
+ # @return [Instapaper::Error]
95
+ def self.from_response_code(code)
96
+ if CLIENT_ERRORS.keys.include?(code)
97
+ ClientError.new(CLIENT_ERRORS[code], code)
98
+ elsif SERVER_ERRORS.keys.include?(code)
99
+ ServerError.new(SERVER_ERRORS[code], code)
100
+ elsif SERVICE_ERRORS.keys.include?(code)
101
+ new(SERVICE_ERRORS[code], code)
102
+ end
103
+ end
104
+
69
105
  # Initializes a new Error object
70
106
  #
71
107
  # @param message [Exception, String]
@@ -1,10 +1,7 @@
1
1
  require 'addressable/uri'
2
2
  require 'http'
3
- require 'json'
4
- require 'net/https'
5
- require 'openssl'
6
- require 'instapaper/error'
7
3
  require 'instapaper/http/headers'
4
+ require 'instapaper/http/response'
8
5
 
9
6
  module Instapaper
10
7
  module HTTP
@@ -27,61 +24,17 @@ module Instapaper
27
24
 
28
25
  # @return [Array, Hash]
29
26
  def perform
30
- perform_request
27
+ raw = @options.delete(:raw)
28
+ response = Instapaper::HTTP::Response.new(perform_request, path, raw)
29
+ response.valid? && response.body
31
30
  end
32
31
 
33
32
  private
34
33
 
35
34
  def perform_request
36
- raw = @options.delete(:raw)
37
35
  @headers = Instapaper::HTTP::Headers.new(@client, @request_method, @uri, @options).request_headers
38
36
  options_key = @request_method == :get ? :params : :form
39
- response = ::HTTP.headers(@headers).public_send(@request_method, @uri.to_s, options_key => @options)
40
- fail_if_error(response, raw)
41
- raw ? response.to_s : parsed_response(response)
42
- end
43
-
44
- def fail_if_error(response, raw)
45
- fail_if_error_unparseable_response(response) unless raw
46
- fail_if_error_in_body(parsed_response(response))
47
- fail_if_error_response_code(response)
48
- end
49
-
50
- def fail_if_error_response_code(response)
51
- return if response.status == 200
52
-
53
- if Instapaper::Error::CODES.include?(response.status.code)
54
- fail Instapaper::Error.from_response(response.status.code, @path)
55
- else
56
- fail Instapaper::Error::ServiceUnavailableError
57
- end
58
- end
59
-
60
- def fail_if_error_unparseable_response(response)
61
- response.parse(:json)
62
- rescue JSON::ParserError
63
- raise Instapaper::Error::ServiceUnavailableError
64
- end
65
-
66
- def fail_if_error_in_body(response)
67
- error = error(response)
68
- fail(error) if error
69
- end
70
-
71
- def error(response)
72
- return unless response.is_a?(Array)
73
- return unless response.size > 0
74
- return unless response.first['type'] == 'error'
75
-
76
- Instapaper::Error.from_response(response.first['error_code'], @path)
77
- end
78
-
79
- def parsed_response(response)
80
- @parsed_response ||= begin
81
- response.parse(:json)
82
- rescue
83
- response.body
84
- end
37
+ ::HTTP.headers(@headers).public_send(@request_method, @uri.to_s, options_key => @options)
85
38
  end
86
39
  end
87
40
  end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'instapaper/error'
3
+
4
+ module Instapaper
5
+ module HTTP
6
+ class Response
7
+ attr_reader :response, :raw_format, :path
8
+ def initialize(response, path, raw_format = false)
9
+ @response = response
10
+ @path = path
11
+ @raw_format = raw_format
12
+ end
13
+
14
+ def body
15
+ raw_format ? response.to_s : parsed
16
+ end
17
+
18
+ def valid?
19
+ !error?
20
+ end
21
+
22
+ def error?
23
+ fail_if_body_unparseable unless raw_format
24
+ fail_if_body_contains_error
25
+ fail_if_http_error
26
+ end
27
+
28
+ private
29
+
30
+ def parsed
31
+ @parsed_response ||= begin
32
+ response.parse(:json)
33
+ rescue
34
+ response.body
35
+ end
36
+ end
37
+
38
+ def fail_if_http_error
39
+ return if response.status.ok?
40
+
41
+ if Instapaper::Error::CODES.include?(response.status.code) # rubocop:disable Style/GuardClause
42
+ raise Instapaper::Error.from_response(response.status.code, path)
43
+ else
44
+ raise Instapaper::Error, 'Unknown Error'
45
+ end
46
+ end
47
+
48
+ def fail_if_body_unparseable
49
+ response.parse(:json)
50
+ rescue JSON::ParserError
51
+ raise Instapaper::Error::ServiceUnavailableError
52
+ end
53
+
54
+ def fail_if_body_contains_error
55
+ return unless parsed.is_a?(Array)
56
+ return if parsed.empty?
57
+ return unless parsed.first['type'] == 'error'
58
+
59
+ raise Instapaper::Error.from_response(parsed.first['error_code'], @path)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -60,6 +60,11 @@ module Instapaper
60
60
  if response.key?('hash')
61
61
  response['instapaper_hash'] = response.delete('hash')
62
62
  end
63
+ if response.key?('bookmarks')
64
+ response['bookmarks'] = response['bookmarks'].collect do |bookmark|
65
+ coerce_hash(bookmark)
66
+ end
67
+ end
63
68
  response
64
69
  end
65
70
  end
@@ -1,3 +1,3 @@
1
1
  module Instapaper
2
- VERSION = '1.0.0.pre3'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instapaper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Agalloco
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-15 00:00:00.000000000 Z
11
+ date: 2017-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
33
+ version: '2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.0'
40
+ version: '2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: multi_json
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +120,7 @@ files:
120
120
  - lib/instapaper/http/headers.rb
121
121
  - lib/instapaper/http/qline_parser.rb
122
122
  - lib/instapaper/http/request.rb
123
+ - lib/instapaper/http/response.rb
123
124
  - lib/instapaper/http/utils.rb
124
125
  - lib/instapaper/user.rb
125
126
  - lib/instapaper/version.rb
@@ -138,14 +139,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
139
  version: 2.0.0
139
140
  required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  requirements:
141
- - - ">"
142
+ - - ">="
142
143
  - !ruby/object:Gem::Version
143
- version: 1.3.1
144
+ version: '0'
144
145
  requirements: []
145
146
  rubyforge_project:
146
- rubygems_version: 2.4.8
147
+ rubygems_version: 2.6.10
147
148
  signing_key:
148
149
  specification_version: 4
149
150
  summary: Ruby Instapaper Client
150
151
  test_files: []
151
- has_rdoc: