cloudconvert 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,14 @@
1
+ module CloudConvert
2
+ class Event < Entity
3
+ include Equalizer.new(:event, :job)
4
+
5
+ # @return [String]
6
+ attr_reader :event
7
+
8
+ # @return [String]
9
+ alias_method :name, :event
10
+
11
+ # @return [Boolean]
12
+ object_attr_reader :Job, :job
13
+ end
14
+ 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 ||= MimeMagic.by_magic(file) || MimeMagic.by_path(file)
6
+ super(file, content_type, *parts)
7
+ end
8
+ end
9
+ end