instapaper 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. data/{PostInstall.txt → .gemtest} +0 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.simplecov +1 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +152 -0
  9. data/Rakefile +13 -4
  10. data/instapaper.gemspec +33 -0
  11. data/lib/faraday/response/raise_http_1xxx.rb +65 -0
  12. data/lib/instapaper.rb +26 -10
  13. data/lib/instapaper/authentication.rb +32 -0
  14. data/lib/instapaper/client.rb +43 -0
  15. data/lib/instapaper/client/account.rb +13 -0
  16. data/lib/instapaper/client/bookmark.rb +81 -0
  17. data/lib/instapaper/client/folder.rb +34 -0
  18. data/lib/instapaper/client/user.rb +14 -0
  19. data/lib/instapaper/configuration.rb +88 -0
  20. data/lib/instapaper/connection.rb +35 -0
  21. data/lib/instapaper/request.rb +22 -9
  22. data/lib/instapaper/version.rb +1 -31
  23. data/spec/faraday/response_spec.rb +22 -0
  24. data/spec/fixtures/access_token.qline +1 -0
  25. data/spec/fixtures/bookmarks_add.json +1 -0
  26. data/spec/fixtures/bookmarks_archive.json +1 -0
  27. data/spec/fixtures/bookmarks_get_text.txt +299 -0
  28. data/spec/fixtures/bookmarks_list.json +5 -0
  29. data/spec/fixtures/bookmarks_move.json +1 -0
  30. data/spec/fixtures/bookmarks_star.json +1 -0
  31. data/spec/fixtures/bookmarks_unarchive.json +1 -0
  32. data/spec/fixtures/bookmarks_unstar.json +1 -0
  33. data/spec/fixtures/bookmarks_update_read_progress.json +1 -0
  34. data/spec/fixtures/folders_add.json +1 -0
  35. data/spec/fixtures/folders_delete.json +1 -0
  36. data/spec/fixtures/folders_list.json +1 -0
  37. data/spec/fixtures/folders_set_order.json +1 -0
  38. data/spec/fixtures/verify_credentials.json +1 -0
  39. data/spec/instapaper/client/account_spec.rb +27 -0
  40. data/spec/instapaper/client/bookmark_spec.rb +234 -0
  41. data/spec/instapaper/client/folder_spec.rb +89 -0
  42. data/spec/instapaper/client/user_spec.rb +28 -0
  43. data/spec/instapaper/client_spec.rb +65 -0
  44. data/spec/instapaper_spec.rb +85 -0
  45. data/spec/spec_helper.rb +44 -0
  46. metadata +230 -99
  47. data/History.txt +0 -3
  48. data/Manifest.txt +0 -43
  49. data/README.rdoc +0 -73
  50. data/config/hoe.rb +0 -73
  51. data/config/requirements.rb +0 -15
  52. data/lib/instapaper/base.rb +0 -113
  53. data/lib/instapaper/constants.rb +0 -37
  54. data/lib/instapaper/exceptions.rb +0 -41
  55. data/lib/instapaper/protocol.rb +0 -47
  56. data/lib/instapaper/request/abstract_request.rb +0 -104
  57. data/lib/instapaper/request/add_url_request.rb +0 -68
  58. data/lib/instapaper/request/authentication_request.rb +0 -60
  59. data/lib/instapaper/request/request_error.rb +0 -34
  60. data/lib/instapaper/request/request_errors.rb +0 -41
  61. data/lib/instapaper/request/request_validation.rb +0 -34
  62. data/lib/instapaper/response.rb +0 -10
  63. data/lib/instapaper/response/abstract_response.rb +0 -38
  64. data/lib/instapaper/response/add_url_success_response.rb +0 -41
  65. data/lib/instapaper/response/authentication_invalid_response.rb +0 -40
  66. data/lib/instapaper/response/authentication_success_response.rb +0 -40
  67. data/lib/instapaper/response/bad_request_response.rb +0 -40
  68. data/lib/instapaper/response/response_builder.rb +0 -61
  69. data/lib/instapaper/response/service_error_response.rb +0 -40
  70. data/script/console +0 -10
  71. data/script/destroy +0 -14
  72. data/script/generate +0 -14
  73. data/script/txt2html +0 -82
  74. data/setup.rb +0 -1585
  75. data/tasks/deployment.rake +0 -34
  76. data/tasks/environment.rake +0 -7
  77. data/tasks/website.rake +0 -17
  78. data/test/test_auth.rb +0 -62
  79. data/test/test_error.rb +0 -81
  80. data/test/test_helper.rb +0 -2
  81. data/test/test_instapaper.rb +0 -9
  82. data/test/test_request.rb +0 -45
  83. data/website/index.html +0 -99
  84. data/website/index.txt +0 -69
  85. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  86. data/website/stylesheets/screen.css +0 -138
  87. data/website/template.html.erb +0 -48
File without changes
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ *.rbc
3
+ .DS_Store
4
+ .bundle
5
+ .rvmrc
6
+ .yardoc
7
+ Gemfile.lock
8
+ coverage/*
9
+ doc/*
10
+ log/*
11
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format=nested
3
+ --backtrace
@@ -0,0 +1 @@
1
+ SimpleCov.start
@@ -0,0 +1,3 @@
1
+ --markup markdown
2
+ -
3
+ LICENSE.md
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Steve Agalloco
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,152 @@
1
+ Instapaper
2
+ =========
3
+ Instapaper is a ruby wrapper for interacting with [Instapaper's Full Developer API](http://www.instapaper.com/api/full). Note that access to the Full API is restricted to Instapaper subscribers only.
4
+
5
+ Installation
6
+ ------------
7
+ gem install instapaper
8
+
9
+ Usage
10
+ -----
11
+
12
+ Instapaper offers full support for all methods exposed through the Full API. Note that Instapaer does not support the request-token/authorize workflow. To obtain an access token, use the `access_token` method.
13
+
14
+ Configuration
15
+ -------------
16
+
17
+ ```ruby
18
+ Instapaper.configure do |config|
19
+ config.consumer_key = YOUR_CONSUMER_KEY
20
+ config.consumer_secret = YOUR_CONSUMER_SECRET
21
+ config.oauth_token = YOUR_OAUTH_TOKEN
22
+ config.oauth_token_secret = YOUR_OAUTH_TOKEN_SECRET
23
+ end
24
+ ```
25
+
26
+ Authentication
27
+ --------------
28
+
29
+ To obtain an access token via xAuth:
30
+
31
+ ```ruby
32
+ Instapaper.access_token(username, password)
33
+ ```
34
+
35
+ You can also verify credentials once you have received tokens:
36
+
37
+ ```ruby
38
+ Instapaper.verify_credentials
39
+ ```
40
+
41
+ Bookmark Operations
42
+ -------------------
43
+
44
+ Retrieve a list of bookmarks:
45
+
46
+ ```ruby
47
+ Instapaper.bookmarks
48
+ ```
49
+
50
+ Add a new bookmark:
51
+
52
+ ```ruby
53
+ Instapaper.add_bookmark('http://someurl.com', :title => 'This is the title', :description => 'This is the description')
54
+ ```
55
+
56
+ Remove a bookmark:
57
+
58
+ ```ruby
59
+ Instapaper.delete_bookmark(bookmark_id)
60
+ ```
61
+
62
+ Update read progress:
63
+
64
+ ```ruby
65
+ Instapaper.update_read_progress(bookmark_id, 0.5)
66
+ ```
67
+
68
+ Star/Un-star a bookmark:
69
+
70
+ ```ruby
71
+ Instapaper.star(bookmark_id)
72
+ Instapaper.unstar(bookmark_id)
73
+ ```
74
+
75
+ Archive/Un-archive a bookmark:
76
+
77
+ ```ruby
78
+ Instapaper.archive(bookmark_id)
79
+ Instapaper.unarchive(bookmark_id)
80
+ ```
81
+
82
+ Move a bookmark to a folder:
83
+
84
+ ```ruby
85
+ Instapaper.move(bookmark_id, folder_id)
86
+ ```
87
+
88
+ Obtain the text of a bookmark:
89
+
90
+ ```ruby
91
+ Instapaper.text(bookmark_id)
92
+ ```
93
+
94
+ Folder Operations
95
+ -----------------
96
+
97
+ To obtain the list of folders:
98
+
99
+ ```ruby
100
+ Instapaper.folders
101
+ ```
102
+
103
+ You can add by passing a name:
104
+
105
+ ```ruby
106
+ Instapaper.add_folder('eventmachine')
107
+ ```
108
+
109
+ And remove folders by referencing a folder by it's id.
110
+
111
+ ```ruby
112
+ Instapaper.delete_folder(folder_id)
113
+ ```
114
+
115
+ Lastly, the folders can be reordered:
116
+
117
+ ```ruby
118
+ Instapaper.set_order(['folder_id1:2','folder_id2:1'])
119
+ ```
120
+
121
+ Restrictions
122
+ ------------
123
+
124
+ Users without an Instapaper Subscription may only invoke the following calls:
125
+
126
+ ```ruby
127
+ Instapaper.access_token
128
+ Instapaper.verify_credentials
129
+ Instapaper.add_bookmark
130
+ Instapaper.folders
131
+ ```
132
+
133
+ Documentation
134
+ -------------
135
+
136
+ [http://rdoc.info/gems/instapaper](http://rdoc.info/gems/instapaper)
137
+
138
+ Note on Patches/Pull Requests
139
+ -----------------------------
140
+
141
+ * Fork the project.
142
+ * Make your feature addition or bug fix.
143
+ * Add tests for it. This is important so I don't break it in a
144
+ future version unintentionally.
145
+ * Commit, do not mess with rakefile, version, or history.
146
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
147
+ * Send me a pull request. Bonus points for topic branches.
148
+
149
+ Copyright
150
+ ---------
151
+
152
+ Copyright (c) 2011 Steve Agalloco. See [LICENSE](https://github.com/spagalloco/instapaper/blob/master/LICENSE.md) for details.
data/Rakefile CHANGED
@@ -1,4 +1,13 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :test => :spec
10
+ task :default => :spec
11
+
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "instapaper/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "instapaper"
7
+ gem.version = Instapaper::VERSION
8
+
9
+ gem.author = "Steve Agalloco"
10
+ gem.email = "steve.agalloco@gmail.com"
11
+ gem.homepage = "https://github.com/spagalloco/instapaper"
12
+ gem.summary = %q{Ruby Instapaper Client}
13
+ gem.description = %q{Ruby Instapaper Client}
14
+
15
+ gem.add_development_dependency('rake', '~> 0.9')
16
+ gem.add_development_dependency('rdiscount', '~> 1.6')
17
+ gem.add_development_dependency('rspec', '~> 2.7')
18
+ gem.add_development_dependency('simplecov', '~> 0.5')
19
+ gem.add_development_dependency('yard', '~> 0.7')
20
+ gem.add_development_dependency('json', '>= 0')
21
+ gem.add_development_dependency('webmock', '~> 1.7')
22
+
23
+ gem.add_runtime_dependency('hashie', '~> 1.1.0')
24
+ gem.add_runtime_dependency('faraday_middleware', '~> 0.7')
25
+ gem.add_runtime_dependency('multi_json', '~> 1.0.3')
26
+ gem.add_runtime_dependency('rash', '~> 0.3')
27
+ gem.add_runtime_dependency('simple_oauth', '~> 0.1')
28
+
29
+ gem.files = `git ls-files`.split("\n")
30
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ gem.require_paths = ["lib"]
33
+ end
@@ -0,0 +1,65 @@
1
+ require 'faraday'
2
+
3
+ # @private
4
+ module Faraday
5
+ # @private
6
+ class Response::RaiseHttp1xxx < Response::Middleware
7
+ def on_complete(env)
8
+ case env[:status].to_i
9
+
10
+ # general errors
11
+
12
+ when 1040
13
+ raise Instapaper::Error.new(error_message(env, "Rate-limit exceeded."))
14
+ when 1041
15
+ raise Instapaper::Error.new(error_message(env, "Subscription account required."))
16
+ when 1042
17
+ raise Instapaper::Error.new(error_message(env, "Application is suspended."))
18
+
19
+ # bookmark errors
20
+
21
+ when 1220
22
+ raise Instapaper::Error.new(error_message(env, "Domain requires full content to be supplied."))
23
+ when 1221
24
+ raise Instapaper::Error.new(error_message(env, "Domain has opted out of Instapaper compatibility."))
25
+ when 1240
26
+ raise Instapaper::Error.new(error_message(env, "Invalid URL specified."))
27
+ when 1241
28
+ raise Instapaper::Error.new(error_message(env, "Invalid or missing bookmark_id."))
29
+ when 1242
30
+ raise Instapaper::Error.new(error_message(env, "Invalid or missing folder_id."))
31
+ when 1243
32
+ raise Instapaper::Error.new(error_message(env, "Invalid or missing progress."))
33
+ when 1244
34
+ raise Instapaper::Error.new(error_message(env, "Invalid or missing progress_timestamp."))
35
+ when 1245
36
+ raise Instapaper::Error.new(error_message(env, "Private bookmarks require supplied content."))
37
+ when 1250
38
+ raise Instapaper::Error.new(error_message(env, "Unexpected error when saving bookmark."))
39
+
40
+ # folder errors
41
+
42
+ when 1250
43
+ raise Instapaper::Error.new(error_message(env, "Invalid or missing title."))
44
+ when 1251
45
+ raise Instapaper::Error.new(error_message(env, "User already has a folder with this title."))
46
+ when 1252
47
+ raise Instapaper::Error.new(error_message(env, "Cannot add bookmarks to this folder."))
48
+
49
+ # operational errors
50
+
51
+ when 1500
52
+ raise Instapaper::Error.new(error_message(env, "Unexpected service error."))
53
+ when 1550
54
+ raise Instapaper::Error.new(error_message(env, "Error generating text version of this URL."))
55
+
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def error_message(env, body=nil)
62
+ "#{env[:method].to_s.upcase} #{env[:url].to_s}: #{[env[:status].to_s + ':', body].compact.join(' ')}."
63
+ end
64
+ end
65
+ end
@@ -1,10 +1,26 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
-
4
- require 'instapaper/version'
5
- require 'instapaper/exceptions'
6
- require 'instapaper/constants'
7
- require 'instapaper/protocol'
8
- require 'instapaper/request'
9
- require 'instapaper/response'
10
- require 'instapaper/base'
1
+ require 'instapaper/configuration'
2
+ require 'instapaper/client'
3
+
4
+ module Instapaper
5
+ extend Configuration
6
+
7
+ # Alias for Instapaper::Client.new
8
+ #
9
+ # @return [Instapaper::Client]
10
+ def self.client(options={})
11
+ Instapaper::Client.new(options)
12
+ end
13
+
14
+ # Delegate to Instapaper::Client
15
+ def self.method_missing(method, *args, &block)
16
+ return super unless client.respond_to?(method)
17
+ client.send(method, *args, &block)
18
+ end
19
+
20
+ def self.respond_to?(method, include_private = false)
21
+ client.respond_to?(method, include_private) || super(method, include_private)
22
+ end
23
+
24
+ # Custom error class for rescuing from all Instapaper errors
25
+ class Error < StandardError; end
26
+ end
@@ -0,0 +1,32 @@
1
+ module Instapaper
2
+ # @private
3
+ module Authentication
4
+ private
5
+
6
+ # Authentication hash
7
+ #
8
+ # @return [Hash]
9
+ def authentication
10
+ {
11
+ :consumer_key => consumer_key,
12
+ :consumer_secret => consumer_secret,
13
+ :token => oauth_token,
14
+ :token_secret => oauth_token_secret
15
+ }
16
+ end
17
+
18
+ def consumer_tokens
19
+ {
20
+ :consumer_key => consumer_key,
21
+ :consumer_secret => consumer_secret
22
+ }
23
+ end
24
+
25
+ # Check whether user is authenticated
26
+ #
27
+ # @return [Boolean]
28
+ def authenticated?
29
+ authentication.values.all?
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,43 @@
1
+ require 'instapaper/connection'
2
+ require 'instapaper/request'
3
+ require 'instapaper/authentication'
4
+
5
+ module Instapaper
6
+ # Wrapper for the Instapaper REST API
7
+ class Client
8
+ # @private
9
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
10
+
11
+ alias :api_endpoint :endpoint
12
+ alias :api_version :version
13
+
14
+ # Creates a new API
15
+ def initialize(options={})
16
+ options = Instapaper.options.merge(options)
17
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
18
+ send("#{key}=", options[key])
19
+ end
20
+ end
21
+
22
+ def endpoint_with_prefix
23
+ api_endpoint + path_prefix
24
+ end
25
+
26
+ include Connection
27
+ include Request
28
+ include Authentication
29
+
30
+ # Require client method modules after initializing the Client class in
31
+ # order to avoid a superclass mismatch error, allowing those modules to be
32
+ # Client-namespaced.
33
+ require 'instapaper/client/account'
34
+ require 'instapaper/client/user'
35
+ require 'instapaper/client/bookmark'
36
+ require 'instapaper/client/folder'
37
+
38
+ include Instapaper::Client::Account
39
+ include Instapaper::Client::User
40
+ include Instapaper::Client::Bookmark
41
+ include Instapaper::Client::Folder
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ module Instapaper
2
+ class Client
3
+ # Defines methods related to accounts
4
+ module Account
5
+
6
+ # Returns the currently logged in user.
7
+ def verify_credentials
8
+ post('account/verify_credentials')
9
+ end
10
+
11
+ end
12
+ end
13
+ end