ilovepdf 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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