cloudconvert 0.0.3 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +17 -18
- data/README.md +234 -39
- data/cloudconvert.gemspec +39 -22
- data/lib/cloudconvert.rb +33 -10
- data/lib/cloudconvert/base.rb +173 -0
- data/lib/cloudconvert/client.rb +107 -0
- data/lib/cloudconvert/collection.rb +15 -0
- data/lib/cloudconvert/entity.rb +21 -0
- data/lib/cloudconvert/error.rb +108 -0
- data/lib/cloudconvert/event.rb +14 -0
- data/lib/cloudconvert/file.rb +9 -0
- data/lib/cloudconvert/job.rb +18 -0
- data/lib/cloudconvert/middleware.rb +9 -0
- data/lib/cloudconvert/resource.rb +9 -0
- data/lib/cloudconvert/resources/jobs.rb +54 -0
- data/lib/cloudconvert/resources/tasks.rb +80 -0
- data/lib/cloudconvert/resources/users.rb +10 -0
- data/lib/cloudconvert/task.rb +43 -0
- data/lib/cloudconvert/user.rb +18 -0
- data/lib/cloudconvert/version.rb +2 -2
- data/lib/cloudconvert/webhook.rb +54 -0
- data/lib/cloudconvert/webhook/processor.rb +29 -0
- metadata +318 -46
- data/.gitignore +0 -17
- data/Gemfile +0 -7
- data/Rakefile +0 -1
- data/lib/cloudconvert/configuration.rb +0 -21
- data/lib/cloudconvert/conversion.rb +0 -111
@@ -0,0 +1,173 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class Base
|
3
|
+
extend Forwardable
|
4
|
+
include Memoizable
|
5
|
+
# @return [Hash]
|
6
|
+
attr_reader :attrs
|
7
|
+
alias to_h attrs
|
8
|
+
alias to_hash to_h
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Define methods that retrieve the value from attributes
|
12
|
+
#
|
13
|
+
# @param attrs [Array, Symbol]
|
14
|
+
def attr_reader(*attrs)
|
15
|
+
attrs.each do |attr|
|
16
|
+
define_attribute_method(attr)
|
17
|
+
define_predicate_method(attr)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Define collection methods from attributes
|
22
|
+
#
|
23
|
+
# @param klass [Symbol]
|
24
|
+
# @param attrs [Array, Symbol]
|
25
|
+
def collection_attr_reader(klass, *attrs)
|
26
|
+
attrs.each do |attr|
|
27
|
+
define_collection_method(attr, klass)
|
28
|
+
define_predicate_method(attr)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Define object methods from attributes
|
33
|
+
#
|
34
|
+
# @param klass [Symbol]
|
35
|
+
# @param attrs [Array, Symbol]
|
36
|
+
def object_attr_reader(klass, *attrs)
|
37
|
+
attrs.each do |attr|
|
38
|
+
define_object_method(attr, klass)
|
39
|
+
define_predicate_method(attr)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Define predicate methods from attributes
|
44
|
+
#
|
45
|
+
# @param attrs [Array, Symbol]
|
46
|
+
def predicate_attr_reader(*attrs)
|
47
|
+
attrs.each do |attr|
|
48
|
+
define_predicate_method(attr)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Define struct methods from attributes
|
53
|
+
#
|
54
|
+
# @param attrs [Array, Symbol]
|
55
|
+
def struct_attr_reader(*attrs)
|
56
|
+
attrs.each do |attr|
|
57
|
+
define_struct_method(attr)
|
58
|
+
define_predicate_method(attr)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Define symbol methods from attributes
|
63
|
+
#
|
64
|
+
# @param attrs [Array, Symbol]
|
65
|
+
def symbol_attr_reader(*attrs)
|
66
|
+
attrs.each do |attr|
|
67
|
+
define_symbol_method(attr)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Define time methods from attributes
|
72
|
+
#
|
73
|
+
# @param attrs [Array, Symbol]
|
74
|
+
def time_attr_reader(*attrs)
|
75
|
+
attrs.each do |attr|
|
76
|
+
define_time_method(attr)
|
77
|
+
define_predicate_method(attr.to_s.gsub(/_at$/, ""), attr)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Dynamically define a method for an attribute
|
84
|
+
#
|
85
|
+
# @param key [Symbol]
|
86
|
+
# @param klass [Symbol]
|
87
|
+
def define_attribute_method(key)
|
88
|
+
define_method(key) do
|
89
|
+
@attrs[key]
|
90
|
+
end
|
91
|
+
memoize(key)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Dynamically define a collection method for an attribute
|
95
|
+
#
|
96
|
+
# @param key [Symbol]
|
97
|
+
# @param klass [Symbol]
|
98
|
+
def define_collection_method(key, klass)
|
99
|
+
define_method(key) do
|
100
|
+
collection = @attrs[key] || []
|
101
|
+
entity = CloudConvert.const_get(klass)
|
102
|
+
Collection.new collection.map { |item| entity.new(item) }
|
103
|
+
end
|
104
|
+
memoize(key)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Dynamically define a predicate method for an attribute
|
108
|
+
#
|
109
|
+
# @param key1 [Symbol]
|
110
|
+
# @param key2 [Symbol]
|
111
|
+
def define_predicate_method(key1, key2 = key1)
|
112
|
+
define_method(:"#{key1}?") do
|
113
|
+
!attr_falsey_or_empty?(key2)
|
114
|
+
end
|
115
|
+
memoize(:"#{key1}?")
|
116
|
+
end
|
117
|
+
|
118
|
+
# Dynamically define a object method for an attribute
|
119
|
+
#
|
120
|
+
# @param key [Symbol]
|
121
|
+
def define_object_method(key, klass)
|
122
|
+
define_method(key) do
|
123
|
+
CloudConvert.const_get(klass).new(@attrs[key]) unless @attrs[key].nil?
|
124
|
+
end
|
125
|
+
memoize(key)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Dynamically define a struct method for an attribute
|
129
|
+
#
|
130
|
+
# @param key [Symbol]
|
131
|
+
def define_struct_method(key)
|
132
|
+
define_method(key) do
|
133
|
+
OpenStruct.new(@attrs[key]) unless @attrs[key].nil?
|
134
|
+
end
|
135
|
+
memoize(key)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Dynamically define a symbol method for an attribute
|
139
|
+
#
|
140
|
+
# @param key [Symbol]
|
141
|
+
def define_symbol_method(key)
|
142
|
+
define_method(key) do
|
143
|
+
@attrs[key].to_sym unless @attrs[key].nil?
|
144
|
+
end
|
145
|
+
memoize(key)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Dynamically define a time method for an attribute
|
149
|
+
#
|
150
|
+
# @param key [Symbol]
|
151
|
+
def define_time_method(key)
|
152
|
+
define_method(key) do
|
153
|
+
Time.parse(@attrs[key]).utc unless @attrs[key].nil?
|
154
|
+
end
|
155
|
+
memoize(key)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Initializes a new object
|
160
|
+
#
|
161
|
+
# @param attrs [Hash]
|
162
|
+
# @return [CloudConvert::Base]
|
163
|
+
def initialize(attrs = {})
|
164
|
+
@attrs = attrs || {}
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def attr_falsey_or_empty?(key)
|
170
|
+
!@attrs[key] || @attrs[key].respond_to?(:empty?) && @attrs[key].empty?
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class Client
|
3
|
+
attr_reader :api_key, :sandbox
|
4
|
+
|
5
|
+
# Initializes a new Client object
|
6
|
+
#
|
7
|
+
# @param options [Hash]
|
8
|
+
# @return [CloudConvert::Client]
|
9
|
+
def initialize(options = {})
|
10
|
+
schema = Schemacop::Schema.new do
|
11
|
+
req! :api_key, :string
|
12
|
+
opt! :sandbox, :boolean, default: false
|
13
|
+
end
|
14
|
+
|
15
|
+
schema.validate! options.reverse_merge!({
|
16
|
+
api_key: ENV["CLOUDCONVERT_API_KEY"],
|
17
|
+
sandbox: ENV["CLOUDCONVERT_SANDBOX"].to_s.downcase == "true",
|
18
|
+
})
|
19
|
+
|
20
|
+
@api_key = options[:api_key]
|
21
|
+
@sandbox = options[:sandbox]
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Resources::Jobs]
|
25
|
+
def jobs
|
26
|
+
@jobs ||= Resources::Jobs.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Resources::Tasks]
|
30
|
+
def tasks
|
31
|
+
@tasks ||= Resources::Tasks.new(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Resources::Users]
|
35
|
+
def users
|
36
|
+
@users ||= Resources::Users.new(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param method [Symbol]
|
40
|
+
# @param path [String]
|
41
|
+
# @param params [Hash]
|
42
|
+
# @return [OpenStruct]
|
43
|
+
def request(method, path, params = {}, &block)
|
44
|
+
response = connection.send(method, path, params, &block)
|
45
|
+
raise CloudConvert::Error.from_response(response) unless response.success?
|
46
|
+
response.body unless response.body.blank?
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param path [String]
|
50
|
+
# @param params [Hash]
|
51
|
+
# @return [OpenStruct]
|
52
|
+
def get(path, params = {}, &block)
|
53
|
+
request(:get, path, params, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param path [String]
|
57
|
+
# @param params [Hash]
|
58
|
+
# @return [OpenStruct]
|
59
|
+
def post(path, params = {}, &block)
|
60
|
+
request(:post, path, params, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param path [String]
|
64
|
+
# @param params [Hash]
|
65
|
+
# @return [OpenStruct]
|
66
|
+
def delete(path, params = {}, &block)
|
67
|
+
request(:delete, path, params, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param url [String]
|
71
|
+
# @return [Tempfile]
|
72
|
+
def download(url, *args, **options)
|
73
|
+
options[:headers] ||= {}
|
74
|
+
options[:headers]["User-Agent"] = USER_AGENT
|
75
|
+
Down.download(url, *args, **options)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# @return [String]
|
81
|
+
def api_host
|
82
|
+
@api_host ||= sandbox ? SANDBOX_URL : API_URL
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Faraday::Client]
|
86
|
+
def connection
|
87
|
+
@connection ||= Faraday.new(url: api_host, headers: headers) do |f|
|
88
|
+
f.adapter Faraday.default_adapter
|
89
|
+
f.request :json
|
90
|
+
f.request :multipart
|
91
|
+
f.use CloudConvert::Middleware::ParseJson, content_type: /\bjson$/
|
92
|
+
f.use FaradayMiddleware::FollowRedirects, callback: lambda { |response, redirect|
|
93
|
+
redirect.request_headers.delete("Content-Length")
|
94
|
+
redirect.request_headers.delete("Content-Type")
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Hash]
|
100
|
+
def headers
|
101
|
+
@headers ||= {
|
102
|
+
"Authorization": "Bearer #{api_key}",
|
103
|
+
"User-Agent": USER_AGENT,
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class Collection < Array
|
3
|
+
attr_reader :links, :meta
|
4
|
+
|
5
|
+
def initialize(items = [], links = {}, meta = {})
|
6
|
+
super(items)
|
7
|
+
@links = links
|
8
|
+
@meta = meta
|
9
|
+
end
|
10
|
+
|
11
|
+
def where(attrs)
|
12
|
+
self.class.new select { |item| attrs.map { |k, v| item.send(k) == v ? true : nil }.compact.length == attrs.length }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class Entity < Base
|
3
|
+
attr_reader :id
|
4
|
+
|
5
|
+
include Equalizer.new(:id)
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def collection(response)
|
9
|
+
CloudConvert::Collection.new(
|
10
|
+
response.data.collect { |item| new(item) },
|
11
|
+
response.links,
|
12
|
+
response.meta,
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def result(response)
|
17
|
+
new response.data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class Error < StandardError
|
3
|
+
# @return [Integer]
|
4
|
+
attr_reader :code
|
5
|
+
|
6
|
+
# @return [OpenStruct]
|
7
|
+
attr_reader :errors
|
8
|
+
|
9
|
+
# Raised when CloudConvert returns a 4xx HTTP status code
|
10
|
+
ClientError = Class.new(self)
|
11
|
+
|
12
|
+
# Raised when CloudConvert returns the HTTP status code 400
|
13
|
+
BadRequest = Class.new(ClientError)
|
14
|
+
|
15
|
+
# Raised when CloudConvert returns the HTTP status code 401
|
16
|
+
Unauthorized = Class.new(ClientError)
|
17
|
+
|
18
|
+
# Raised when CloudConvert returns the HTTP status code 402
|
19
|
+
PaymentRequired = Class.new(ClientError)
|
20
|
+
|
21
|
+
# Raised when CloudConvert returns the HTTP status code 403
|
22
|
+
Forbidden = Class.new(ClientError)
|
23
|
+
|
24
|
+
# Raised when CloudConvert returns the HTTP status code 413
|
25
|
+
RequestEntityTooLarge = Class.new(ClientError)
|
26
|
+
|
27
|
+
# Raised when CloudConvert returns the HTTP status code 404
|
28
|
+
NotFound = Class.new(ClientError)
|
29
|
+
|
30
|
+
# Raised when CloudConvert returns the HTTP status code 406
|
31
|
+
NotAcceptable = Class.new(ClientError)
|
32
|
+
|
33
|
+
# Raised when CloudConvert returns the HTTP status code 422
|
34
|
+
UnprocessableEntity = Class.new(ClientError)
|
35
|
+
|
36
|
+
# Raised when CloudConvert returns the HTTP status code 429
|
37
|
+
TooManyRequests = Class.new(ClientError)
|
38
|
+
|
39
|
+
# Raised when CloudConvert returns a 5xx HTTP status code
|
40
|
+
ServerError = Class.new(self)
|
41
|
+
|
42
|
+
# Raised when CloudConvert returns the HTTP status code 500
|
43
|
+
InternalServerError = Class.new(ServerError)
|
44
|
+
|
45
|
+
# Raised when CloudConvert returns the HTTP status code 502
|
46
|
+
BadGateway = Class.new(ServerError)
|
47
|
+
|
48
|
+
# Raised when CloudConvert returns the HTTP status code 503
|
49
|
+
ServiceUnavailable = Class.new(ServerError)
|
50
|
+
|
51
|
+
# Raised when CloudConvert returns the HTTP status code 504
|
52
|
+
GatewayTimeout = Class.new(ServerError)
|
53
|
+
|
54
|
+
# Raised when CloudConvert returns a media related error
|
55
|
+
MediaError = Class.new(self)
|
56
|
+
|
57
|
+
# Raised when CloudConvert returns an InvalidMedia error
|
58
|
+
InvalidMedia = Class.new(MediaError)
|
59
|
+
|
60
|
+
# Raised when CloudConvert returns a media InternalError error
|
61
|
+
MediaInternalError = Class.new(MediaError)
|
62
|
+
|
63
|
+
# Raised when CloudConvert returns an UnsupportedMedia error
|
64
|
+
UnsupportedMedia = Class.new(MediaError)
|
65
|
+
|
66
|
+
# Raised when an operation subject to timeout takes too long
|
67
|
+
TimeoutError = Class.new(self)
|
68
|
+
|
69
|
+
ERRORS = {
|
70
|
+
400 => CloudConvert::Error::BadRequest,
|
71
|
+
401 => CloudConvert::Error::Unauthorized,
|
72
|
+
402 => CloudConvert::Error::PaymentRequired,
|
73
|
+
403 => CloudConvert::Error::Forbidden,
|
74
|
+
404 => CloudConvert::Error::NotFound,
|
75
|
+
406 => CloudConvert::Error::NotAcceptable,
|
76
|
+
413 => CloudConvert::Error::RequestEntityTooLarge,
|
77
|
+
422 => CloudConvert::Error::UnprocessableEntity,
|
78
|
+
429 => CloudConvert::Error::TooManyRequests,
|
79
|
+
500 => CloudConvert::Error::InternalServerError,
|
80
|
+
502 => CloudConvert::Error::BadGateway,
|
81
|
+
503 => CloudConvert::Error::ServiceUnavailable,
|
82
|
+
504 => CloudConvert::Error::GatewayTimeout,
|
83
|
+
}.freeze
|
84
|
+
|
85
|
+
class << self
|
86
|
+
# Create a new error from an HTTP response
|
87
|
+
#
|
88
|
+
# @param response [Faraday::Response]
|
89
|
+
# @return [CloudConvert::Error]
|
90
|
+
def from_response(response)
|
91
|
+
klass = ERRORS[response.status] || self
|
92
|
+
klass.new(response.body.message, response.body.code, response.body.errors)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Initializes a new Error object
|
97
|
+
#
|
98
|
+
# @param message [Exception, String]
|
99
|
+
# @param code [Integer]
|
100
|
+
# @return [CloudConvert::Error]
|
101
|
+
def initialize(message = "", code = nil, errors = {})
|
102
|
+
super(message)
|
103
|
+
|
104
|
+
@code = code
|
105
|
+
@errors = errors
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module CloudConvert
|
2
|
+
class File < Faraday::FilePart
|
3
|
+
def initialize(file, content_type = nil, *parts)
|
4
|
+
content_type ||= "text/plain" if file.is_a? StringIO
|
5
|
+
content_type ||= Marcel::Magic.by_magic(file) || Marcel::Magic.by_path(file)
|
6
|
+
super(file, content_type, *parts)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|