ilovepdf 1.0.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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +12 -0
  3. data/.gitignore +14 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +142 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +17 -0
  11. data/bin/setup +8 -0
  12. data/ilovepdf.gemspec +35 -0
  13. data/lib/ilovepdf.rb +36 -0
  14. data/lib/ilovepdf/errors.rb +51 -0
  15. data/lib/ilovepdf/file.rb +36 -0
  16. data/lib/ilovepdf/ilovepdf.rb +142 -0
  17. data/lib/ilovepdf/response.rb +36 -0
  18. data/lib/ilovepdf/task.rb +195 -0
  19. data/lib/ilovepdf/tool/compress.rb +20 -0
  20. data/lib/ilovepdf/tool/imagepdf.rb +27 -0
  21. data/lib/ilovepdf/tool/merge.rb +13 -0
  22. data/lib/ilovepdf/tool/officepdf.rb +13 -0
  23. data/lib/ilovepdf/tool/pagenumber.rb +40 -0
  24. data/lib/ilovepdf/tool/pdfa.rb +26 -0
  25. data/lib/ilovepdf/tool/pdfjpg.rb +22 -0
  26. data/lib/ilovepdf/tool/protect.rb +13 -0
  27. data/lib/ilovepdf/tool/repair.rb +12 -0
  28. data/lib/ilovepdf/tool/rotate.rb +12 -0
  29. data/lib/ilovepdf/tool/split.rb +35 -0
  30. data/lib/ilovepdf/tool/unlock.rb +12 -0
  31. data/lib/ilovepdf/tool/watermark.rb +49 -0
  32. data/lib/ilovepdf/version.rb +3 -0
  33. data/samples/compress_advanced.rb +25 -0
  34. data/samples/compress_basic.rb +14 -0
  35. data/samples/merge_advanced.rb +22 -0
  36. data/samples/merge_basic.rb +18 -0
  37. data/samples/pdfa_advanced.rb +21 -0
  38. data/samples/pdfa_basic.rb +17 -0
  39. data/samples/repair_advanced.rb +21 -0
  40. data/samples/repair_basic.rb +17 -0
  41. data/samples/rotate_advanced.rb +21 -0
  42. data/samples/rotate_basic.rb +17 -0
  43. data/samples/split_advanced.rb +32 -0
  44. data/samples/split_advanced_merge.rb +30 -0
  45. data/samples/split_basic.rb +17 -0
  46. data/samples/try_catch_errors.rb +46 -0
  47. data/samples/unlock_advanced.rb +21 -0
  48. data/samples/unlock_basic.rb +17 -0
  49. data/samples/watermark_advanced.rb +57 -0
  50. data/samples/watermark_basic.rb +20 -0
  51. data/uploads/sample_pdf.pdf +0 -0
  52. metadata +209 -0
@@ -0,0 +1,36 @@
1
+ module Ilovepdf
2
+ class Response
3
+ attr_accessor :response
4
+
5
+ def initialize(response)
6
+ raise ArgumentError.new('Argument must be of type \'RestClient::Response\'') unless response.is_a? ::RestClient::Response
7
+ self.response = response
8
+ end
9
+
10
+ def headers
11
+ self.response.headers
12
+ end
13
+
14
+ def body
15
+ return @body if @body
16
+ is_json = (/application\/json/i =~ self.response.headers[:content_type]) != nil
17
+ if is_json
18
+ @body ||= JSON.parse(self.response.body)
19
+ else
20
+ @body = self.response.body
21
+ end
22
+ end
23
+
24
+ def raw_body
25
+ self.response.body
26
+ end
27
+
28
+ def code
29
+ self.response.code
30
+ end
31
+
32
+ def success?
33
+ self.response.code.to_s[0] == '2'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,195 @@
1
+ module Ilovepdf
2
+ class Task < Ilovepdf
3
+ attr_accessor :task_id, :tool, :packaged_filename, :output_filename,
4
+ :ignore_errors, :ignore_password, :try_pdf_repair
5
+
6
+ API_PARAMS = []
7
+
8
+ def initialize(public_key, secret_key)
9
+ super(public_key, secret_key)
10
+ response = perform_create_request
11
+ self.worker_server = 'https://' + response.body['server']
12
+ self.task_id = response.body['task']
13
+
14
+ # Assign default values
15
+ self.ignore_errors = true
16
+ self.ignore_password = true
17
+ self.try_pdf_repair = true
18
+ end
19
+
20
+ def assign_meta_value(key, value)
21
+ meta_values[key] = value
22
+ end
23
+
24
+ def files
25
+ @files ||= []
26
+ end
27
+
28
+ def add_file(filepath)
29
+ raise ArgumentError.new("No file exists in '#{filepath}'") unless ::File.exist?(filepath)
30
+ file = perform_upload_request(filepath)
31
+ files << file
32
+ files.last
33
+ end
34
+
35
+ def add_file_from_url(url)
36
+ file = perform_upload_url_request(url)
37
+ files << file
38
+ files.last
39
+ end
40
+
41
+ def download(path=nil)
42
+ download_file(path)
43
+ end
44
+
45
+ # [API Methods] Actions on task
46
+
47
+ def status
48
+ http_response = query_task_status(worker_server,task_id)
49
+ end
50
+
51
+ def execute
52
+ perform_process_request
53
+ end
54
+
55
+ def delete!
56
+ send_request('delete', 'task/' + self.task_id)
57
+ end
58
+
59
+ def delete_file(file)
60
+ raise Error.new("File was already deleted") if file.deleted?
61
+ file_was_found = files.find{|f| f.server_filename == file.server_filename }
62
+ raise Error.new("File to delete not found") if !file_was_found
63
+ response = perform_deletefile_request(file)
64
+ if response.success?
65
+ file.mark_as_deleted
66
+ new_files = files.reject{|f| f.server_filename == file.server_filename }
67
+ send(:files=, new_files)
68
+ else
69
+ raise ApiError.new(response, custom_msg: "No error ocurred but response was not successful when deleting the desired file")
70
+ end
71
+ true
72
+ end
73
+
74
+ def enable_file_encryption(enable, new_encrypt_key = nil)
75
+ raise Error.new("Encryption mode cannot be assigned after uploading the files") if files.size > 0
76
+ super(enable, new_encrypt_key)
77
+ end
78
+
79
+ private
80
+
81
+ # set meta values as http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf (page 844)
82
+ def meta_values
83
+ @meta_values ||= {}
84
+ end
85
+
86
+ def files=(new_array_of_files)
87
+ @files = new_array_of_files
88
+ end
89
+
90
+ def download_file path
91
+ response = perform_filedownload_request
92
+ content_disposition = response.headers[:content_disposition]
93
+
94
+ if match_data = /filename\*\=utf-8\'\'([\W\w]+)/.match(content_disposition)
95
+ filename = URI.unescape(match_data[1].gsub('"', ''))
96
+ else
97
+ match_data = / .*filename=\"([\W\w]+)\"/.match(content_disposition)
98
+ filename = match_data[1].gsub('"', '')
99
+ end
100
+
101
+ if path
102
+ path = Pathname.new(path).to_s if path.is_a?(Pathname)
103
+ path.chop! if path.end_with? '/'
104
+ else
105
+ path = '.'
106
+ end
107
+ destination = "#{path}/#{filename}"
108
+ ::File.open(destination, 'wb'){|file| file.write(response.raw_body) }
109
+ file = response.raw_body
110
+ true
111
+ end
112
+
113
+ # [HTTP request methods]
114
+ def perform_deletefile_request(file)
115
+ body = {
116
+ task: self.task_id,
117
+ server_filename: file.server_filename,
118
+ v: API_VERSION
119
+ }
120
+ response = send_request('post', 'upload/delete', body: body)
121
+ end
122
+
123
+ def perform_filedownload_request
124
+ response = send_request('get', 'download/' + self.task_id, body: {v: API_VERSION})
125
+ end
126
+
127
+ def perform_process_request
128
+ body = {
129
+ task: self.task_id,
130
+ tool: self.tool,
131
+ packaged_filename: self.packaged_filename,
132
+ output_filename: self.output_filename,
133
+ ignore_errors: self.ignore_errors,
134
+ ignore_password: self.ignore_password,
135
+ try_pdf_repair: self.try_pdf_repair,
136
+ meta: meta_values,
137
+ v: API_VERSION,
138
+ }.merge(file_submit_params)
139
+ .merge(extract_api_params)
140
+
141
+ response = send_request('post', 'process', body: body)
142
+ response
143
+ end
144
+
145
+ def perform_create_request
146
+ request_opts = {
147
+ body: {v: API_VERSION}
148
+ }
149
+ response = send_request('get', 'start/' + self.tool.to_s, request_opts)
150
+ end
151
+
152
+ def perform_upload_request filepath
153
+ request_opts = {
154
+ body: {
155
+ multipart: true,
156
+ v: API_VERSION,
157
+ task: self.task_id,
158
+ file: ::File.new(filepath, 'rb')
159
+ }
160
+ }
161
+ # filepath
162
+ response = send_request('post', 'upload', request_opts)
163
+ File.new(response.body['server_filename'], Pathname.new(filepath).basename.to_s)
164
+ end
165
+
166
+ def perform_upload_url_request url
167
+ request_opts = {
168
+ body: {
169
+ multipart: true,
170
+ v: API_VERSION,
171
+ task: self.task_id,
172
+ cloud_file: url
173
+ }
174
+ }
175
+ response = send_request('post', 'upload', request_opts)
176
+ File.new(response.body['server_filename'], Pathname.new(url).basename.to_s)
177
+ end
178
+
179
+ def file_submit_params
180
+ h = {files:{}}
181
+ files.each_with_index do |f, i|
182
+ h[:files][i.to_s] = f.file_options
183
+ end
184
+ h
185
+ end
186
+
187
+ def extract_api_params
188
+ {}.tap do |h|
189
+ self.class::API_PARAMS.each{ |param_name|
190
+ h[param_name] = send(param_name)
191
+ }
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,20 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Compress < ::Ilovepdf::Task
4
+ API_PARAMS = [:compression_level]
5
+ attr_accessor *API_PARAMS
6
+
7
+ COMPRESSION_LEVEL_VALUES = ["extreme", "recommended", "low"]
8
+
9
+ def initialize(public_key, secret_key)
10
+ self.tool = :compress
11
+ super(public_key, secret_key)
12
+ end
13
+
14
+ def compression_level= level
15
+ raise Errors::ArgumentEnumError.new(COMPRESSION_LEVEL_VALUES) unless COMPRESSION_LEVEL_VALUES.include? level
16
+ @compression_level = level
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Imagepdf < ::Ilovepdf::Task
4
+ API_PARAMS = [:orientation, :margin, :pagesize, :merge_after]
5
+ attr_accessor *API_PARAMS
6
+
7
+ ORIENTATION_VALUES = ['portrait', 'landscape']
8
+ PAGESIZE_VALUES = ['fit', 'A4', 'letter']
9
+
10
+ def initialize(public_key, secret_key)
11
+ self.tool = :imagepdf
12
+ self.merge_after = true
13
+ super(public_key, secret_key)
14
+ end
15
+
16
+ def orientation=(new_val)
17
+ raise Errors::ArgumentEnumError.new(ORIENTATION_VALUES) unless ORIENTATION_VALUES.include? new_val
18
+ @orientation = new_val
19
+ end
20
+
21
+ def pagesize=(new_val)
22
+ raise Errors::ArgumentEnumError.new(PAGESIZE_VALUES) unless PAGESIZE_VALUES.include? new_val
23
+ @pagesize = new_val
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Merge < ::Ilovepdf::Task
4
+ API_PARAMS = []
5
+ attr_accessor *API_PARAMS
6
+
7
+ def initialize(public_key, secret_key)
8
+ self.tool = :merge
9
+ super(public_key, secret_key)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Officepdf < ::Ilovepdf::Task
4
+ API_PARAMS = []
5
+ attr_accessor *API_PARAMS
6
+
7
+ def initialize(public_key, secret_key)
8
+ self.tool = :officepdf
9
+ super(public_key, secret_key)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Pagenumber < ::Ilovepdf::Task
4
+ API_PARAMS = [
5
+ :facing_pages, :first_cover, :pages, :starting_number, :vertical_position,
6
+ :horizontal_position, :vertical_position_adjustment, :horizontal_position_adjustment,
7
+ :font_family, :font_style, :font_size, :font_color, :text
8
+ ]
9
+
10
+ attr_accessor *API_PARAMS
11
+
12
+ VERTICAL_POSITION_VALUES = ['bottom', 'top']
13
+ HORIZONTAL_POSITION_VALUES = ['left', 'middle', 'right']
14
+ FONT_FAMILY_VALUES = [ 'Arial', 'Arial Unicode MS', 'Verdana', 'Courier',
15
+ 'Times New Roman', 'Comic Sans MS',
16
+ 'WenQuanYi Zen Hei', 'Lohit Marathi'
17
+ ]
18
+
19
+ def initialize(public_key, secret_key)
20
+ self.tool = :pagenumber
21
+ super(public_key, secret_key)
22
+ end
23
+
24
+ def vertical_position=(new_val)
25
+ raise Errors::ArgumentEnumError.new(VERTICAL_POSITION_VALUES) unless VERTICAL_POSITION_VALUES.include? new_val
26
+ @vertical_position = new_val
27
+ end
28
+
29
+ def horizontal_position=(new_val)
30
+ raise Errors::ArgumentEnumError.new(HORIZONTAL_POSITION_VALUES) unless HORIZONTAL_POSITION_VALUES.include? new_val
31
+ @horizontal_position = new_val
32
+ end
33
+
34
+ def font_family=(new_val)
35
+ raise Errors::ArgumentEnumError.new(FONT_FAMILY_VALUES) unless FONT_FAMILY_VALUES.include? new_val
36
+ @font_family = new_val
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Pdfa < ::Ilovepdf::Task
4
+ API_PARAMS = [:conformance]
5
+ attr_accessor *API_PARAMS
6
+
7
+ CONFORMANCE_VALUES = ['pdfa-1b', 'pdfa-1a', 'pdfa-2b', 'pdfa-2u',
8
+ 'pdfa-2a', 'pdfa-3b', 'pdfa-3u', 'pdfa-3a'
9
+ ]
10
+
11
+ def initialize(public_key, secret_key)
12
+ self.tool = :pdfa
13
+ super(public_key, secret_key)
14
+ end
15
+
16
+ def conformance= new_val
17
+ raise Errors::ArgumentEnumError.new(CONFORMANCE_VALUES) unless CONFORMANCE_VALUES.include? new_val
18
+ @conformance = new_val
19
+ end
20
+
21
+ def conformance
22
+ @conformance ||= 'default'
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Pdfjpg < ::Ilovepdf::Task
4
+ API_PARAMS = [:mode]
5
+
6
+ MODE_VALUES = ['pages', 'extract']
7
+
8
+ def initialize(public_key, secret_key)
9
+ self.tool = :pdfjpg
10
+ super(public_key, secret_key)
11
+ end
12
+
13
+ def mode=(new_val)
14
+ raise Errors::ArgumentEnumError.new(MODE_VALUES) unless MODE_VALUES.include?(new_val)
15
+ @mode = new_val
16
+ end
17
+ def mode
18
+ @mode
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Protect < ::Ilovepdf::Task
4
+ API_PARAMS = [:password]
5
+ attr_accessor *API_PARAMS
6
+
7
+ def initialize(public_key, secret_key)
8
+ self.tool = :protect
9
+ super(public_key, secret_key)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Repair < ::Ilovepdf::Task
4
+ API_PARAMS = []
5
+
6
+ def initialize(public_key, secret_key)
7
+ self.tool = :repair
8
+ super(public_key, secret_key)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Rotate < ::Ilovepdf::Task
4
+ API_PARAMS = []
5
+
6
+ def initialize(public_key, secret_key)
7
+ self.tool = :rotate
8
+ super(public_key, secret_key)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ module Ilovepdf
2
+ module Tool
3
+ class Split < ::Ilovepdf::Task
4
+ API_PARAMS = [:ranges, :split_mode, :fixed_range, :remove_pages, :merge_after]
5
+ attr_accessor *API_PARAMS
6
+
7
+ def initialize(public_key, secret_key)
8
+ self.tool = :split
9
+ super(public_key, secret_key)
10
+ end
11
+
12
+ def fixed_range=(range=1)
13
+ @split_mode = 'fixed_range'
14
+ @fixed_range = range
15
+ end
16
+
17
+ def remove_pages=(pages)
18
+ @split_mode = 'remove_pages'
19
+ @remove_pages = pages
20
+ end
21
+
22
+ def ranges=(pages)
23
+ @split_mode = 'ranges'
24
+ @ranges = pages
25
+ end
26
+
27
+ def merge_after=(value)
28
+ @merge_after = value
29
+ end
30
+ def merge_after
31
+ @merge_after ||= false
32
+ end
33
+ end
34
+ end
35
+ end