instapaper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +43 -0
  3. data/PostInstall.txt +0 -0
  4. data/README.rdoc +73 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +73 -0
  7. data/config/requirements.rb +15 -0
  8. data/lib/instapaper.rb +10 -0
  9. data/lib/instapaper/base.rb +113 -0
  10. data/lib/instapaper/constants.rb +37 -0
  11. data/lib/instapaper/exceptions.rb +41 -0
  12. data/lib/instapaper/protocol.rb +47 -0
  13. data/lib/instapaper/request.rb +9 -0
  14. data/lib/instapaper/request/abstract_request.rb +104 -0
  15. data/lib/instapaper/request/add_url_request.rb +68 -0
  16. data/lib/instapaper/request/authentication_request.rb +60 -0
  17. data/lib/instapaper/request/request_error.rb +34 -0
  18. data/lib/instapaper/request/request_errors.rb +41 -0
  19. data/lib/instapaper/request/request_validation.rb +34 -0
  20. data/lib/instapaper/response.rb +10 -0
  21. data/lib/instapaper/response/abstract_response.rb +38 -0
  22. data/lib/instapaper/response/add_url_success_response.rb +41 -0
  23. data/lib/instapaper/response/authentication_invalid_response.rb +40 -0
  24. data/lib/instapaper/response/authentication_success_response.rb +40 -0
  25. data/lib/instapaper/response/bad_request_response.rb +40 -0
  26. data/lib/instapaper/response/response_builder.rb +61 -0
  27. data/lib/instapaper/response/service_error_response.rb +40 -0
  28. data/lib/instapaper/version.rb +33 -0
  29. data/script/console +10 -0
  30. data/script/destroy +14 -0
  31. data/script/generate +14 -0
  32. data/script/txt2html +82 -0
  33. data/setup.rb +1585 -0
  34. data/tasks/deployment.rake +34 -0
  35. data/tasks/environment.rake +7 -0
  36. data/tasks/website.rake +17 -0
  37. data/test/test_auth.rb +62 -0
  38. data/test/test_error.rb +81 -0
  39. data/test/test_helper.rb +2 -0
  40. data/test/test_instapaper.rb +9 -0
  41. data/test/test_request.rb +45 -0
  42. data/website/index.html +99 -0
  43. data/website/index.txt +69 -0
  44. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  45. data/website/stylesheets/screen.css +138 -0
  46. data/website/template.html.erb +48 -0
  47. metadata +114 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0 2009-02-17
2
+
3
+ Initial Release
data/Manifest.txt ADDED
@@ -0,0 +1,43 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/instapaper.rb
9
+ lib/instapaper/base.rb
10
+ lib/instapaper/constants.rb
11
+ lib/instapaper/exceptions.rb
12
+ lib/instapaper/protocol.rb
13
+ lib/instapaper/request.rb
14
+ lib/instapaper/request/abstract_request.rb
15
+ lib/instapaper/request/add_url_request.rb
16
+ lib/instapaper/request/authentication_request.rb
17
+ lib/instapaper/request/request_error.rb
18
+ lib/instapaper/request/request_errors.rb
19
+ lib/instapaper/request/request_validation.rb
20
+ lib/instapaper/response.rb
21
+ lib/instapaper/response/abstract_response.rb
22
+ lib/instapaper/response/add_url_success_response.rb
23
+ lib/instapaper/response/authentication_invalid_response.rb
24
+ lib/instapaper/response/authentication_success_response.rb
25
+ lib/instapaper/response/bad_request_response.rb
26
+ lib/instapaper/response/response_builder.rb
27
+ lib/instapaper/response/service_error_response.rb
28
+ lib/instapaper/version.rb
29
+ script/console
30
+ script/destroy
31
+ script/generate
32
+ script/txt2html
33
+ setup.rb
34
+ tasks/deployment.rake
35
+ tasks/environment.rake
36
+ tasks/website.rake
37
+ test/test_helper.rb
38
+ test/test_instapaper.rb
39
+ website/index.html
40
+ website/index.txt
41
+ website/javascripts/rounded_corners_lite.inc.js
42
+ website/stylesheets/screen.css
43
+ website/template.html.erb
data/PostInstall.txt ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1,73 @@
1
+ = instapaper
2
+
3
+ * http://instapaper.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ The instapaper gem provides a neat interface to the Instapaper API.
8
+
9
+ == SYNOPSIS:
10
+
11
+ # "password" is optional
12
+ base = Instapaper::Base.new("username","password")
13
+
14
+ # Test authentication (not required to add url)
15
+ result = base.authenticate
16
+ # => Instapaper::Response::AuthenticationSuccessResponse
17
+
18
+ result.code # => 200
19
+
20
+ # Add URL
21
+ result = base.add("http://example.org/some-article.html")
22
+ # => Instapaper::Response::AddURLSuccess
23
+
24
+ result.code # => 200
25
+
26
+ # Bad Auth
27
+ base = Instapaper::Base.new("baduser","badpass")
28
+ result = base.authenticate
29
+ # => Instapaper::Response::AuthenticationInvalidResponse
30
+
31
+ result.code # => 403
32
+
33
+ # Advanced usage
34
+ base = Instapaper::Base.new("username","password")
35
+ options = {:url => "http://example.org/some-article.html", :title => "MyArticle"}
36
+ request = AddURLRequest.new(options,"username","password")
37
+
38
+ base.secure? # => true (as default)
39
+
40
+ base.use_clear_protocol!
41
+ # => connection will now use HTTP instead of HTTPS
42
+
43
+ response = base.send_request(request)
44
+
45
+
46
+ == INSTALL:
47
+
48
+ * sudo gem install instapaper
49
+
50
+ == LICENSE:
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2009 FIXME full name
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/config/hoe.rb ADDED
@@ -0,0 +1,73 @@
1
+ require 'instapaper/version'
2
+
3
+ AUTHOR = 'Douglas Willcocks' # can also be an array of Authors
4
+ EMAIL = "douglas.willcocks@gmail.com"
5
+ DESCRIPTION = "A simple wrapper for the Instapaper API"
6
+ GEM_NAME = 'instapaper' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'instapaper' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ # ['activesupport', '>= 1.3.1']
12
+ ] # An array of rubygem dependencies [name, version]
13
+
14
+ @config_file = "~/.rubyforge/user-config.yml"
15
+ @config = nil
16
+ RUBYFORGE_USERNAME = "unknown"
17
+ def rubyforge_username
18
+ unless @config
19
+ begin
20
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
21
+ rescue
22
+ puts <<-EOS
23
+ ERROR: No rubyforge config file found: #{@config_file}
24
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
25
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
26
+ EOS
27
+ exit
28
+ end
29
+ end
30
+ RUBYFORGE_USERNAME.replace @config["username"]
31
+ end
32
+
33
+
34
+ REV = nil
35
+ # UNCOMMENT IF REQUIRED:
36
+ # REV = YAML.load(`svn info`)['Revision']
37
+ VERS = Instapaper::VERSION::STRING + (REV ? ".#{REV}" : "")
38
+ RDOC_OPTS = ['--quiet', '--title', 'instapaper documentation',
39
+ "--opname", "index.html",
40
+ "--line-numbers",
41
+ "--main", "README",
42
+ "--inline-source"]
43
+
44
+ class Hoe
45
+ def extra_deps
46
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
47
+ @extra_deps
48
+ end
49
+ end
50
+
51
+ # Generate all the Rake tasks
52
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
53
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
54
+ p.developer(AUTHOR, EMAIL)
55
+ p.description = DESCRIPTION
56
+ p.summary = DESCRIPTION
57
+ p.url = HOMEPATH
58
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
59
+ p.test_globs = ["test/**/test_*.rb"]
60
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
61
+
62
+ # == Optional
63
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
64
+ #p.extra_deps = EXTRA_DEPENDENCIES
65
+
66
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
67
+ end
68
+
69
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
70
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
71
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
72
+ $hoe.rsync_args = '-av --delete --ignore-errors'
73
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
data/lib/instapaper.rb ADDED
@@ -0,0 +1,10 @@
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'
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2009 Douglas Willcocks
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+
25
+ # Provide a simple wrapper interface to Instapaper
26
+
27
+ require 'net/http'
28
+ require 'net/https'
29
+ require 'uri'
30
+
31
+ module Instapaper
32
+ class Base
33
+
34
+ include Protocol
35
+ include Constants
36
+ include Request
37
+ include Response
38
+ include Exceptions
39
+
40
+ # Instatiate a new Instapaper object that will act as the adaptor the Instapaper
41
+ # API.
42
+ #
43
+ # Usernames are mandatory, but passwords are optional as on Instapaper
44
+ def initialize(username, password = nil)
45
+ @username = username
46
+ @password = password
47
+ @protocol = PROTOCOLS[:secure]
48
+ end
49
+
50
+ # Add a URL to Instapaper
51
+ #
52
+ # See Base#get_add_request
53
+ def add(url_data, options = {})
54
+ req = get_add_request(url_data,options)
55
+
56
+ return send_request(req)
57
+ end
58
+
59
+ # Create a request to add a URL to instapaper
60
+ #
61
+ # Takes a hash of options:
62
+ #
63
+ # :title
64
+ # plain text, no HTML, UTF-8
65
+ # :selection
66
+ # plain text, no HTML, UTF-8
67
+ # :auto_title
68
+ # Replaces title. Instapaper will crawl the URL to detect a title.
69
+ # Use this if you do not know a title for the URL, such as when it’s an
70
+ # inline link somewhere that hasn’t been opened.
71
+ # Defaults to 1
72
+ #
73
+ def get_add_request(url_data, options = {})
74
+
75
+ raise InvalidRequestDetailsException unless options.is_a?(Hash)
76
+
77
+ options[:url] = url_data
78
+ AddURLRequest.new(options,@username,@password)
79
+ end
80
+
81
+ # Test the authentication credentials
82
+ def authenticate
83
+ req = AuthenticationRequest.new(@username,@password)
84
+
85
+ return send_request(req)
86
+ end
87
+
88
+ # Do the actual communication with the server
89
+ def send_request(request)
90
+
91
+ request.use_clear_protocol! unless secure?
92
+ request.prepare
93
+
94
+ url = URI.parse(request.url)
95
+ req = Net::HTTP::Post.new(url.path)
96
+
97
+ req.set_form_data(request.post_data)
98
+
99
+ http = Net::HTTP.new(url.host,url.port)
100
+
101
+ http.use_ssl = secure?
102
+
103
+ # Instapaper triggers an invalid SSL, so there's no way of telling
104
+ # if it's being spoofed. May as well just turn off warnings.
105
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
106
+
107
+ res = http.request(req)
108
+
109
+ return ResponseBuilder.build(res,request)
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2009 Douglas Willcocks
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ # Various constants
25
+
26
+ module Instapaper
27
+ module Constants #:nodoc: all
28
+
29
+ PROTOCOLS = {:clear => "http", :secure => "https"}.freeze
30
+ HOST = "instapaper.com"
31
+ API_BASE = "api"
32
+
33
+ API_AUTH = "authenticate"
34
+ API_ADD = "add"
35
+
36
+ end
37
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2009 Douglas Willcocks
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ # Errors thrown
25
+
26
+ module Instapaper
27
+ module Exceptions
28
+
29
+ class InstapaperException < Exception; end #:nodoc:
30
+
31
+ # Thrown when the request object was built with incomplete data
32
+ class InvalidRequestDetailsException < InstapaperException; end
33
+
34
+ # Thrown when trying to use an abstract request as an actual request
35
+ class AbstractRequestException < InstapaperException; end
36
+
37
+ # Thrown when the server returns a response code we don't know how to handle
38
+ class UnrecognisedResponseCodeException < InstapaperException; end
39
+
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (c) 2009 Douglas Willcocks
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ module Instapaper
25
+
26
+ module Protocol
27
+
28
+ include Constants
29
+
30
+ # Make the request using HTTPS (default)
31
+ def use_secure_protocol!
32
+ @protocol = PROTOCOLS[:secure]
33
+ end
34
+
35
+ # Make the request using HTTP (username/password passed in clear)
36
+ def use_clear_protocol!
37
+ @protocol = PROTOCOLS[:clear]
38
+ end
39
+
40
+ # Are we using HTTPS?
41
+ def secure?
42
+ @protocol == PROTOCOLS[:secure]
43
+ end
44
+
45
+ end
46
+
47
+ end