optidash 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 28b445eb3b610f52877cc3ecdde81aa8b6d92dfd88de615f5ceada2ea99729e3
4
+ data.tar.gz: b433e816bf1eef3a07d062b4f75515bf7a3d88a583cf33ba91a55d3a035b5458
5
+ SHA512:
6
+ metadata.gz: '053489a1e64b5e6f2a958d2ce98e1d5577a06ee622df557077505b9fcaf7411b9acdcc0260757c4416a122b5ed18405c6c7e512f7f27352100102c3f147eedff'
7
+ data.tar.gz: c82c266fffb1523d8b4cca16b7442f2fa6d1eb66a2e08e249695c1844b1789d211630e302174be7c8119bd512e1503467cc952359c0b248f9c27bae0367ed7e6
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.idea/*
10
+ .ruby-version
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Optidash UG <support@optidash.ai> (https://optidash.ai)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ <p align="center"><a href="https://optidash.ai"><img src="media/logotype.png" alt="Optidash" width="143" height="45"/></a></p>
2
+
3
+ <p align="center">
4
+ Optidash is a modern, AI-powered image optimization and processing API.<br>We will drastically speed-up your websites and save you money on bandwidth and storage.
5
+ </p>
6
+
7
+ ---
8
+ <p align="center">
9
+ <strong>The official Ruby integration for the Optidash API.</strong><br>
10
+ <br>
11
+ <img src="https://img.shields.io/gem/v/optidash?style=flat&color=success"/>
12
+ <img src="https://img.shields.io/snyk/vulnerabilities/github/optidash-ai/optidash-ruby?style=flat&color=success"/>
13
+ <img src="https://img.shields.io/github/issues-raw/optidash-ai/optidash-ruby?style=flat&color=success"/>
14
+ <img src="https://img.shields.io/github/license/optidash-ai/optidash-ruby?style=flat&color=success"/>
15
+ <img src="https://img.shields.io/twitter/follow/optidashAI?label=Follow%20Us&style=flat&color=success&logo=twitter"/>
16
+ </p>
17
+
18
+ ---
19
+
20
+ ### Documentation
21
+ See the [Optidash API docs](https://docs.optidash.ai/).
22
+
23
+ ### Installation
24
+ ```bash
25
+ $ gem install optidash
26
+ ```
27
+
28
+ ### Quick examples
29
+ Optidash API enables you to provide your images for optimization and processing in two ways - by uploading them directly to the API ([Image Upload](https://docs.optidash.ai/requests/image-upload)) or by providing a publicly available image URL ([Image Fetch](https://docs.optidash.ai/requests/image-fetch)).
30
+
31
+ You may also choose your preferred [response method](https://docs.optidash.ai/introduction#choosing-response-method-and-format) on a per-request basis. By default, the Optidash API will return a [JSON response](https://docs.optidash.ai/responses/json-response-format) with rich metadata pertaining to input and output images. Alternatively, you can use [binary responses](https://docs.optidash.ai/responses/binary-responses). When enabled, the API will respond with a full binary representation of the resulting (output) image. This Ruby integration exposes two convenience methods for interacting with binary responses: `.toFile()` and `.toBuffer()`.
32
+
33
+ #### Image upload
34
+ Here is a quick example of uploading a local file for processing. It calls `.toJSON()` at a final step and instructs the API to return a JSON response.
35
+
36
+ ```ruby
37
+ require "optidash"
38
+
39
+ # Pass your Optidash API Key to the constructor
40
+ opti = Optidash.new("your-api-key")
41
+
42
+ # Upload an image from disk, resize it to 100 x 75,
43
+ # automatically enhance, and adjust sharpness parameter.
44
+ # You'll find the full JSON metadata within the `meta` variable
45
+ err, meta = (
46
+ opti
47
+ .upload("path/to/input.jpg")
48
+ .optimize(
49
+ compression: "medium"
50
+ )
51
+ .resize(
52
+ width: 100,
53
+ height: 75
54
+ )
55
+ .auto(
56
+ enhance: true
57
+ )
58
+ .adjust(
59
+ unsharp: 10
60
+ )
61
+ .to_json()
62
+ )
63
+
64
+ abort(err) if err
65
+ ```
66
+
67
+ #### Image fetch
68
+ If you already have your source visuals publicly available online, we recommend using Image Fetch by default. That way you only have to send a JSON payload containing image URL and processing steps. This method is also much faster than uploading a full binary representation of the image.
69
+
70
+ ```ruby
71
+ require "optidash"
72
+
73
+ # Pass your Optidash API Key to the constructor
74
+ opti = Optidash.new("your-api-key")
75
+
76
+ # Provide a publicly available image URL with `.fetch()` method,
77
+ # apply Gaussian blur using highly optimized PNG as the output format.
78
+ # We'll also use `.toFile()` method and stream the output image to disk
79
+ err, meta = (
80
+ opti
81
+ .fetch("https://www.website.com/image.jpg")
82
+ .optimize(
83
+ compression: "medium"
84
+ )
85
+ .filter(
86
+ blur: (
87
+ mode: "gaussian",
88
+ value: 10
89
+ }
90
+ )
91
+ .output(
92
+ format: "png"
93
+ )
94
+ .to_file("path/to/output.png")
95
+ )
96
+
97
+ abort(err) if err
98
+ ```
99
+
100
+ ### License
101
+ This software is distributed under the MIT License. See the [LICENSE](LICENSE) file for more information.
Binary file
@@ -0,0 +1,19 @@
1
+ require "json"
2
+ require "rest-client"
3
+ require "uri"
4
+ require "optidash/version"
5
+ require "optidash/errors"
6
+ require "optidash/request"
7
+ require "optidash/response"
8
+ require "optidash/client"
9
+
10
+ module Optidash
11
+
12
+ ##
13
+ # Making Client constructor public
14
+ # to avoid Optidash::Client.new invocation
15
+
16
+ def self.new(*args)
17
+ Client.new(*args)
18
+ end
19
+ end
@@ -0,0 +1,132 @@
1
+ module Optidash
2
+ ##
3
+ # Main Client class, responsible for entire interaction with the API
4
+
5
+ class Client
6
+ def initialize(api_key)
7
+ @api_key = api_key
8
+ end
9
+
10
+ ##
11
+ # Prepares Fetch request
12
+ # @param url [String] web location of a file we wan't to transform via api
13
+
14
+ def fetch(url)
15
+ validate_request :fetch
16
+
17
+ # initiating the request
18
+ @request = Optidash::Request::Fetch.new(@api_key, @proxy)
19
+
20
+ # and preparing data for the request
21
+ @request.data[:url] = url
22
+ self
23
+ end
24
+
25
+
26
+ ##
27
+ # Prepares Upload request
28
+ # @param path [String] local file path
29
+
30
+ def upload(path)
31
+ validate_request :upload
32
+
33
+ # initiating the request
34
+ @request = Optidash::Request::Upload.new(@api_key, path, @proxy)
35
+ self
36
+ end
37
+
38
+
39
+ ##
40
+ # Returns response containing only JSON metadata
41
+
42
+ def to_json
43
+ @request.perform
44
+ end
45
+
46
+
47
+ ##
48
+ # Returns response containing JSON metadata and saves received binary file
49
+ # @param path [String] file destination
50
+
51
+ def to_file(path)
52
+ if path.nil?
53
+ raise Optidash::Errors::NoPathProvided, "No save path provided"
54
+ end
55
+
56
+ validate_binary_operations
57
+ @request.perform(binary: true, save_path: path)
58
+ end
59
+
60
+
61
+ ##
62
+ # Returns response containing JSON metadata and binary file buffer
63
+
64
+ def to_buffer
65
+ validate_binary_operations
66
+ @request.perform(binary: true)
67
+ end
68
+
69
+ ##
70
+ # Sets request proxy
71
+
72
+ def proxy(url = nil)
73
+ return self if url.nil?
74
+ validate_url(url)
75
+ # adding proxy if request instance already exists
76
+ @request ? @request.proxy = url : @proxy = url
77
+ self
78
+ end
79
+
80
+
81
+ ##
82
+ # Meta programmed operation methods - every single one of them does
83
+ # the same thing: adds operation to be performed along with its params
84
+ # to the request data
85
+
86
+ %i(optimize adjust auto border crop mask output padding resize response scale store filter watermark webhook cdn flip).each do |method|
87
+ define_method method do |value = {}|
88
+ return self if value.empty? || !value.respond_to?(:merge)
89
+ @request.data[method] = value
90
+ self
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+
97
+ ##
98
+ # Validates if we can perform request operation, i.e. if fetch was called
99
+ # upload should throw an exception and the other way around. So we don't
100
+ # chain two types of requests
101
+ #
102
+ # @param type [Symbol] request type which we want to perform
103
+
104
+ def validate_request(type)
105
+ return if @request.nil? || @request.type == type
106
+ raise Optidash::Errors::RequestTypeConflict.new(@request.type, type)
107
+ end
108
+
109
+
110
+ ##
111
+ # Validates if particular operations are valid for binary responses.
112
+
113
+ def validate_binary_operations
114
+ if @request.data[:webhook]
115
+ raise Optidash::Errors::OperationNotSupported, "Binary responses are not supported when using Webhooks"
116
+ end
117
+
118
+ if @request.data[:store]
119
+ raise Optidash::Errors::OperationNotSupported, "Binary responses are not supported when using External Storage"
120
+ end
121
+ end
122
+
123
+
124
+ ##
125
+ # Validates proxy url
126
+
127
+ def validate_url(url)
128
+ return if url =~ /\A#{URI::regexp(['http', 'https'])}\z/
129
+ raise Optidash::Errors::InvalidProxyUrl, "Proxy url is not valid"
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,17 @@
1
+ module Optidash
2
+
3
+ ##
4
+ # Handling errors and app exceptions
5
+
6
+ class Errors
7
+ class RequestTypeConflict < StandardError
8
+ def initialize(type1, type2)
9
+ super("current type: #{type1}, attempted: #{type2}")
10
+ end
11
+ end
12
+
13
+ class NoPathProvided < StandardError; end
14
+ class OperationNotSupported < StandardError; end
15
+ class InvalidProxyUrl < StandardError; end
16
+ end
17
+ end
@@ -0,0 +1,134 @@
1
+ module Optidash
2
+
3
+ ##
4
+ # Types of request along with their slightly differing implementations
5
+
6
+ class Request
7
+
8
+ ##
9
+ # Base class.
10
+ # Should be inherited by Fetch and Upload classes.
11
+
12
+ class Base
13
+ attr_reader :type
14
+ attr_accessor :data
15
+ attr_accessor :proxy
16
+
17
+ API_URL = "https://api.optidash.ai/1.0"
18
+
19
+
20
+ ##
21
+ # Constructor. Passing api key for authentication
22
+
23
+ def initialize(key, proxy = nil)
24
+
25
+ ##
26
+ # Setting initial options for the request
27
+
28
+ @options = {
29
+ user: key,
30
+ password: "",
31
+ method: :post,
32
+ url: "#{API_URL}/#{@type}",
33
+ ssl_ca_file: File.dirname(__FILE__) + '/../data/cacert.pem'
34
+ }
35
+
36
+ @proxy = proxy
37
+
38
+ ##
39
+ # Request data, which will be sent do API server
40
+
41
+ @data = {}
42
+ end
43
+
44
+
45
+ ##
46
+ # Performs actual request, sending entire data set options:
47
+ # - binary [Boolean] indicates whether request should return binary response or not
48
+ # - save_path [String|NilClass] save location for binary file, if needed
49
+
50
+ def perform(binary: false, save_path: nil)
51
+ @data.merge!(response: { mode: "binary" }) if binary
52
+
53
+ Optidash::Response.new(
54
+ RestClient::Request.execute(@options.merge(
55
+ payload: request_data,
56
+ headers: headers(binary: binary),
57
+ proxy: proxy
58
+ )),
59
+ save_path: save_path
60
+ ).data
61
+ rescue RestClient::ExceptionWithResponse => e
62
+ Optidash::Response.new(e.response).data
63
+ end
64
+
65
+ private
66
+
67
+
68
+ ##
69
+ # Prepares request headers, appending x-optidash-binary header if necessary.
70
+
71
+ def headers(binary: false)
72
+ @headers ||= {}
73
+ @headers["x-optidash-binary"] = 1 if binary
74
+ @headers
75
+ end
76
+ end
77
+
78
+
79
+ ##
80
+ # Responsible for handling Fetch requests
81
+
82
+ class Fetch < Base
83
+ def initialize(key)
84
+ @type = :fetch
85
+ super(key)
86
+ end
87
+
88
+ ##
89
+ # Returns fetch request data, which is a simple JSON
90
+
91
+ def request_data
92
+ @data.to_json
93
+ end
94
+
95
+ private
96
+
97
+ def headers(binary: false)
98
+ @headers ||= { content_type: :json }
99
+ super
100
+ end
101
+ end
102
+
103
+
104
+ ##
105
+ # Responsible for handling Upload requests
106
+
107
+ class Upload < Base
108
+ def initialize(key, upload_path, proxy = nil)
109
+ @type = :upload
110
+ @upload_path = upload_path
111
+ super(key, proxy)
112
+ end
113
+
114
+ def perform(binary: false, save_path: nil)
115
+ unless File.exist?(@upload_path)
116
+ return "Input file #{@upload_path} does not exist", nil, nil
117
+ end
118
+ super
119
+ end
120
+
121
+
122
+ ##
123
+ # Returns upload request data. Multipart containing uploaded file
124
+ # and operations performed on it
125
+
126
+ def request_data
127
+ {
128
+ file: File.new(@upload_path, "rb"),
129
+ data: @data.to_json
130
+ }
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,68 @@
1
+ module Optidash
2
+
3
+ ##
4
+ # Builds an object containing response data
5
+
6
+ class Response
7
+ def initialize(object, save_path: nil)
8
+ @object = object
9
+ @save_path = save_path
10
+ fetch_metadata
11
+ return unless @error.nil?
12
+
13
+ binary_response if binary?
14
+ end
15
+
16
+ def data
17
+ result = [@error, @metadata]
18
+ result << @file if binary? && @save_path.nil? && @file
19
+ result
20
+ end
21
+
22
+ private
23
+
24
+ def binary?
25
+ !@object.headers[:x_optidash_meta].nil?
26
+ end
27
+
28
+
29
+ ##
30
+ # Extracts the metadata either from the response body
31
+ # or X-Optidash-Meta header if the binary response was in use
32
+
33
+ def fetch_metadata
34
+ data = JSON.parse(@object.headers[:x_optidash_metadata] || @object.body)
35
+
36
+ if data["success"]
37
+ @metadata = data
38
+ else
39
+ @error = data["message"]
40
+ end
41
+ rescue JSON::ParserError
42
+ @error = "Unable to parse JSON response from "
43
+ @error += (binary? ? "X-Optidash-Meta header" : "the Optidash Image API")
44
+ end
45
+
46
+
47
+ ##
48
+ # Handles binary response and
49
+ # saves the file or stores it as a buffer
50
+
51
+ def binary_response
52
+ return save_file if @save_path
53
+ @file = @object.body
54
+ end
55
+
56
+
57
+ ##
58
+ # Saves binary response to disk
59
+
60
+ def save_file
61
+ @file = File.open(@save_path, "wb")
62
+ @file.write(@object.body)
63
+ @file.close
64
+ rescue
65
+ @error = "Unable to save resulting image at `#{@save_path}` location"
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module Optidash
2
+ VERSION = "1.0.0"
3
+ end
Binary file
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "optidash"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "optidash"
10
+ spec.version = Optidash::VERSION
11
+ spec.summary = "Official Ruby integration for Optidash API"
12
+ spec.description = "Optidash: AI-powered image optimization and processing API. We will drastically speed-up your websites and save you money on bandwidth and storage."
13
+ spec.author = ["Optidash UG"]
14
+ spec.email = ["support@optidash.com"]
15
+ spec.homepage = "https://optidash.ai"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 2.0'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+
24
+ spec.add_dependency 'json', '~> 2.0.3'
25
+ spec.add_dependency 'rest-client', '~> 2.0.1'
26
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: optidash
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Optidash UG
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.1
69
+ description: 'Optidash: AI-powered image optimization and processing API. We will
70
+ drastically speed-up your websites and save you money on bandwidth and storage.'
71
+ email:
72
+ - support@optidash.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - lib/data/cacert.pem
82
+ - lib/optidash.rb
83
+ - lib/optidash/client.rb
84
+ - lib/optidash/errors.rb
85
+ - lib/optidash/request.rb
86
+ - lib/optidash/response.rb
87
+ - lib/optidash/version.rb
88
+ - media/logotype.png
89
+ - optidash.gemspec
90
+ homepage: https://optidash.ai
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.0.3
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Official Ruby integration for Optidash API
113
+ test_files: []