imagekitio 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +517 -0
- data/Rakefile +27 -0
- data/lib/carrierwave/storage/ik_file.rb +50 -0
- data/lib/carrierwave/storage/imagekit_store.rb +68 -0
- data/lib/carrierwave/support/uri_filename.rb +10 -0
- data/lib/imagekit/constants/defaults.rb +20 -0
- data/lib/imagekit/constants/errors.rb +71 -0
- data/lib/imagekit/constants/file.rb +5 -0
- data/lib/imagekit/constants/supported_transformation.rb +44 -0
- data/lib/imagekit/constants/url.rb +9 -0
- data/lib/imagekit/file.rb +133 -0
- data/lib/imagekit/imagekit.rb +108 -0
- data/lib/imagekit/resource.rb +55 -0
- data/lib/imagekit/sdk/version.rb +5 -0
- data/lib/imagekit/url.rb +228 -0
- data/lib/imagekit/utils/calculation.rb +36 -0
- data/lib/imagekit/utils/formatter.rb +29 -0
- data/lib/imagekitio.rb +72 -0
- data/lib/imagekitio/railtie.rb +4 -0
- data/lib/tasks/imagekitio/imagekitio_tasks.rake +4 -0
- metadata +124 -0
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Imagekit::Sdk'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'bundler/gem_tasks'
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs << 'test'
|
23
|
+
t.pattern = 'test/**/*_test.rb'
|
24
|
+
t.verbose = false
|
25
|
+
end
|
26
|
+
|
27
|
+
task default: :test
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Storage
|
3
|
+
class IKFile
|
4
|
+
# Initialize as required.
|
5
|
+
|
6
|
+
def initialize(identifier)
|
7
|
+
@identifier=JSON.parse(identifier)
|
8
|
+
ik_config=Rails.application.config.imagekit
|
9
|
+
@imagekit=ImageKit::ImageKitClient.new(ik_config[:private_key],ik_config[:public_key],ik_config[:url_endpoint])
|
10
|
+
end
|
11
|
+
|
12
|
+
# Duck-type methods for CarrierWave::SanitizedFile.
|
13
|
+
def content_type
|
14
|
+
"image/jpg"
|
15
|
+
end
|
16
|
+
def public_url
|
17
|
+
@identifier['url']
|
18
|
+
end
|
19
|
+
def url(options = {})
|
20
|
+
@identifier['url']
|
21
|
+
end
|
22
|
+
|
23
|
+
def fileId
|
24
|
+
@identifier['fileId']
|
25
|
+
end
|
26
|
+
def filename(options = {})
|
27
|
+
@identifier['name']
|
28
|
+
end
|
29
|
+
def read
|
30
|
+
end
|
31
|
+
def size
|
32
|
+
end
|
33
|
+
def delete
|
34
|
+
# file_id=@identifier['fileId']
|
35
|
+
begin
|
36
|
+
@imagekit.delete_file(fileId)
|
37
|
+
rescue
|
38
|
+
fileId
|
39
|
+
end
|
40
|
+
# binding.pry
|
41
|
+
# return nil
|
42
|
+
end
|
43
|
+
def exists?
|
44
|
+
end
|
45
|
+
# Others... ?
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'base64'
|
4
|
+
module CarrierWave
|
5
|
+
module Storage
|
6
|
+
class ImageKitStore < Abstract
|
7
|
+
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
@cache_called = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def store!(file)
|
14
|
+
file.delete
|
15
|
+
end
|
16
|
+
|
17
|
+
def retrieve!(identifier)
|
18
|
+
|
19
|
+
IKFile.new(identifier)
|
20
|
+
end
|
21
|
+
|
22
|
+
def cache!(new_file)
|
23
|
+
new_file.move_to(::File.expand_path(uploader.cache_path, uploader.root), uploader.permissions, uploader.directory_permissions, true)
|
24
|
+
rescue Errno::EMLINK, Errno::ENOSPC => e
|
25
|
+
raise(e) if @cache_called
|
26
|
+
@cache_called = true
|
27
|
+
|
28
|
+
# NOTE: Remove cached files older than 10 minutes
|
29
|
+
clean_cache!(600)
|
30
|
+
|
31
|
+
cache!(new_file)
|
32
|
+
end
|
33
|
+
|
34
|
+
def retrieve_from_cache!(identifier)
|
35
|
+
CarrierWave::SanitizedFile.new(::File.expand_path(uploader.cache_path(identifier), uploader.root))
|
36
|
+
resp=@client.get(identifier)
|
37
|
+
# binding.pry
|
38
|
+
IKFile.new(resp)
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_dir!(path)
|
42
|
+
if path
|
43
|
+
begin
|
44
|
+
Dir.rmdir(::File.expand_path(path, uploader.root))
|
45
|
+
rescue Errno::ENOENT
|
46
|
+
# Ignore: path does not exist
|
47
|
+
rescue Errno::ENOTDIR
|
48
|
+
# Ignore: path is not a dir
|
49
|
+
rescue Errno::ENOTEMPTY, Errno::EEXIST
|
50
|
+
# Ignore: dir is not empty
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def clean_cache!(seconds)
|
56
|
+
Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), CarrierWave.root)).each do |dir|
|
57
|
+
# generate_cache_id returns key formated TIMEINT-PID(-COUNTER)-RND
|
58
|
+
time = dir.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map(&:to_i)
|
59
|
+
time = Time.at(*time)
|
60
|
+
if time < (Time.now.utc - seconds)
|
61
|
+
FileUtils.rm_rf(dir)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Enum for defaults
|
4
|
+
|
5
|
+
class Default
|
6
|
+
TRANSFORMATION_POSITION = "path"
|
7
|
+
QUERY_TRANSFORMATION_POSITION = "query"
|
8
|
+
VALID_TRANSFORMATION_POSITION = [TRANSFORMATION_POSITION,
|
9
|
+
QUERY_TRANSFORMATION_POSITION,].freeze
|
10
|
+
DEFAULT_TIMESTAMP = "9999999999"
|
11
|
+
TRANSFORMATION_PARAMETER = "tr"
|
12
|
+
CHAIN_TRANSFORM_DELIMITER = ":"
|
13
|
+
TRANSFORM_DELIMITER = ","
|
14
|
+
TRANSFORM_KEY_VALUE_DELIMITER = "-"
|
15
|
+
|
16
|
+
SIGNATURE_PARAMETER = "ik-s"
|
17
|
+
TIMESTAMP_PARAMETER = "ik-t"
|
18
|
+
TIMESTAMP = "9999999999"
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
MANDATORY_INIT_MISSING = {
|
2
|
+
'message': "Missing public_key or private_key or url_endpoint during ImageKit initialization",
|
3
|
+
help: "",
|
4
|
+
}
|
5
|
+
INVALID_TRANSFORMATION_POS = {'message': "Invalid transformationPosition parameter",
|
6
|
+
help: "",}
|
7
|
+
INVALID_URL_GENERATION_PARAM = {'message': "Invalid url parameter", help: ""}
|
8
|
+
INVALID_TRANSFORMATION_OPTIONS = {
|
9
|
+
'message': "Invalid transformation parameter options",
|
10
|
+
help: "",
|
11
|
+
}
|
12
|
+
CACHE_PURGE_URL_MISSING = {'message': "Missing URL parameter for this request",
|
13
|
+
help: "",}
|
14
|
+
CACHE_PURGE_STATUS_ID_MISSING = {'message': "Missing Request ID parameter for this request",
|
15
|
+
help: "",}
|
16
|
+
FILE_ID_MISSING = {'message': "Missing File ID parameter for this request",
|
17
|
+
help: "",}
|
18
|
+
UPDATE_DATA_MISSING = {'message': "Missing file update data for this request",
|
19
|
+
help: "",}
|
20
|
+
|
21
|
+
UPDATE_DATA_TAGS_INVALID = {'message': "Invalid tags parameter for this request",
|
22
|
+
help: "tags should be passed as null or an array like ['tag1', 'tag2']",}.freeze
|
23
|
+
|
24
|
+
UPDATE_DATA_COORDS_INVALID =
|
25
|
+
{'message': "Invalid custom_coordinates parameter for this request",
|
26
|
+
help: "custom_coordinates should be passed as null or a string like 'x,y,width,height'",}
|
27
|
+
|
28
|
+
LIST_FILES_INPUT_MISSING = {
|
29
|
+
'message': "Missing options for list files",
|
30
|
+
help: "If you do not want to pass any parameter for listing, pass an empty object",
|
31
|
+
}
|
32
|
+
MISSING_FILE_URL = {'message': "Missing file_url for purge_cache", help: ""}
|
33
|
+
MISSING_UPLOAD_DATA = {'message': "Missing data for upload", help: ""}
|
34
|
+
MISSING_UPLOAD_FILE_PARAMETER = {
|
35
|
+
'message': "Missing file parameter for upload",
|
36
|
+
help: "",
|
37
|
+
}
|
38
|
+
MISSING_UPLOAD_FILENAME_PARAM = {
|
39
|
+
'message': "Missing fileName parameter for upload",
|
40
|
+
help: "",
|
41
|
+
}
|
42
|
+
|
43
|
+
INVALID_PHASH_VALUE =
|
44
|
+
{
|
45
|
+
'message': "Invalid pHash value",
|
46
|
+
help: "Both pHash strings must be valid hexadecimal numbers",
|
47
|
+
}
|
48
|
+
|
49
|
+
MISSING_PHASH_VALUE = {
|
50
|
+
'message': "Missing pHash value",
|
51
|
+
help: "Please pass two pHash values",
|
52
|
+
}
|
53
|
+
UNEQUAL_STRING_LENGTH = {
|
54
|
+
'': "Unequal pHash string length",
|
55
|
+
help: "For distance calculation, the two pHash strings must have equal length",
|
56
|
+
}
|
57
|
+
|
58
|
+
MISSING_UPLOAD_FILE_PARAMETER = {'message': "Missing file parameter for upload",
|
59
|
+
'help': "",}
|
60
|
+
MISSING_UPLOAD_FILENAME_PARAM = {
|
61
|
+
'message': "Missing fileName parameter for upload",
|
62
|
+
'help': "",
|
63
|
+
}
|
64
|
+
|
65
|
+
INVALID_PHASH_VALUE = {'message': "Invalid pHash value",
|
66
|
+
'help': "Both pHash strings must be valid hexadecimal numbers",}
|
67
|
+
|
68
|
+
MISSING_PHASH_VALUE = {'message': "Missing pHash value",
|
69
|
+
'help': "Please pass two pHash values",}
|
70
|
+
UNEQUAL_STRING_LENGTH = {'message': "Unequal pHash string length",
|
71
|
+
'help': "For distance calculation, the two pHash strings must have equal length",}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
SUPPORTED_TRANS = {
|
2
|
+
'height': "h",
|
3
|
+
'width': "w",
|
4
|
+
'aspect_ratio': "ar",
|
5
|
+
'quality': "q",
|
6
|
+
'crop': "c",
|
7
|
+
'crop_mode': "cm",
|
8
|
+
'x': "x",
|
9
|
+
'y': "y",
|
10
|
+
'focus': "fo",
|
11
|
+
'format': "f",
|
12
|
+
'radius': "r",
|
13
|
+
'background': "bg",
|
14
|
+
'border': "bo",
|
15
|
+
'rotation': "rt",
|
16
|
+
'blur': "bl",
|
17
|
+
'named': "n",
|
18
|
+
'overlay_image': "oi",
|
19
|
+
'overlay_x': "ox",
|
20
|
+
'overlay_y': "oy",
|
21
|
+
'overlay_focus': "ofo",
|
22
|
+
'overlay_height': "oh",
|
23
|
+
'overlay_width': "ow",
|
24
|
+
'overlay_text': "ot",
|
25
|
+
'overlay_text_font_size': "ots",
|
26
|
+
'overlay_text_font_family': "otf",
|
27
|
+
'overlay_text_color': "otc",
|
28
|
+
'overlay_alpha': "oa",
|
29
|
+
'overlay_text_typography': "ott",
|
30
|
+
'overlay_background': "obg",
|
31
|
+
'overlay_image_trim': "oit",
|
32
|
+
'progressive': "pr",
|
33
|
+
'lossless': "lo",
|
34
|
+
'trim': "t",
|
35
|
+
'metadata': "md",
|
36
|
+
'color_profile': "cp",
|
37
|
+
'default_image': "di",
|
38
|
+
'dpr': "dpr",
|
39
|
+
'effect_sharpen': "e-sharpen",
|
40
|
+
'effect_usm': "e-usm",
|
41
|
+
'effect_contrast': "e-contrast",
|
42
|
+
'effect_gray': "e-grayscale",
|
43
|
+
'original': "orig",
|
44
|
+
}
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./constants/errors"
|
4
|
+
require_relative "./constants/file"
|
5
|
+
require_relative "./constants/url"
|
6
|
+
|
7
|
+
require_relative "./utils/formatter"
|
8
|
+
|
9
|
+
class ImageKitFile
|
10
|
+
# This File class holds file related operations like
|
11
|
+
# upload, list etc
|
12
|
+
def initialize(req_obj)
|
13
|
+
@req_obj = req_obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload(file, file_name, options)
|
17
|
+
# uploads files with required arguments
|
18
|
+
# supports bot url and binary
|
19
|
+
raise ArgumentError, MISSING_UPLOAD_FILE_PARAMETER unless file
|
20
|
+
raise ArgumentError, MISSING_UPLOAD_FILE_PARAMETER unless file_name
|
21
|
+
options = validate_upload_options(options || {})
|
22
|
+
if options.is_a?(FalseClass)
|
23
|
+
raise ArgumentError, "Invalid Upload option"
|
24
|
+
else
|
25
|
+
headers = @req_obj.create_headers
|
26
|
+
payload = {multipart: true, file: file, fileName: file_name}.merge(options)
|
27
|
+
|
28
|
+
url = "#{URL::BASE_URL}#{URL::UPLOAD}"
|
29
|
+
@req_obj.request("post", url, headers, payload)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def update_details(file_id, options)
|
34
|
+
# Update file detail by file_id and options
|
35
|
+
|
36
|
+
unless (options.key? :tags) || (options.key? :custom_coordinates)
|
37
|
+
raise ArgumentError, UPDATE_DATA_MISSING
|
38
|
+
end
|
39
|
+
unless options.fetch(:tags, []).is_a?(Array)
|
40
|
+
raise ArgumentError, UPDATE_DATA_TAGS_INVALID
|
41
|
+
end
|
42
|
+
unless options.fetch(:custom_coordinates, "").is_a?(String)
|
43
|
+
raise ArgumentError, UPDATE_DATA_COORDS_INVALID
|
44
|
+
end
|
45
|
+
url = "#{URL::BASE_URL}/#{file_id}/details/"
|
46
|
+
headers = @req_obj.create_headers
|
47
|
+
payload = request_formatter(options)
|
48
|
+
@req_obj.request("patch", url, headers, payload.to_json)
|
49
|
+
end
|
50
|
+
|
51
|
+
def list(options)
|
52
|
+
# returns list of files on ImageKit Server
|
53
|
+
# :options dictionary of options
|
54
|
+
formatted_options = request_formatter(options)
|
55
|
+
raise KeyError(LIST_FILES_INPUT_MISSING) unless formatted_options.is_a?(Hash)
|
56
|
+
url = URL::BASE_URL
|
57
|
+
headers = @req_obj.create_headers.update({params: options})
|
58
|
+
@req_obj.request("get", url, headers, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def details(file_identifier)
|
62
|
+
# Get detail of file by file_identifier
|
63
|
+
url = "#{URL::BASE_URL}/#{file_identifier}/details/"
|
64
|
+
headers = @req_obj.create_headers
|
65
|
+
@req_obj.request("get", url, headers)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_metadata(file_id)
|
69
|
+
# Get metadata of a file by file_id
|
70
|
+
url = "#{URL::BASE_URL}/#{file_id}/metadata"
|
71
|
+
@req_obj.request("get", url, @req_obj.create_headers)
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete(file_id)
|
75
|
+
# Delete a file_id by file_id
|
76
|
+
url = "#{URL::BASE_URL}/#{file_id}"
|
77
|
+
headers = @req_obj.create_headers
|
78
|
+
@req_obj.request("delete", url, headers)
|
79
|
+
end
|
80
|
+
|
81
|
+
def batch_delete(file_ids)
|
82
|
+
url = "#{URL::BASE_URL}#{URL::BULK_FILE_DELETE}"
|
83
|
+
payload = {'fileIds': file_ids}
|
84
|
+
@req_obj.request("post", url, @req_obj.create_headers, payload.to_json)
|
85
|
+
end
|
86
|
+
|
87
|
+
def purge_cache(file_url)
|
88
|
+
|
89
|
+
# purges cache from server by file_url
|
90
|
+
|
91
|
+
url = "#{URL::BASE_URL}/purge"
|
92
|
+
payload = {'url': file_url}
|
93
|
+
@req_obj.request("post", url, @req_obj.create_headers, payload)
|
94
|
+
end
|
95
|
+
|
96
|
+
def purge_cache_status(request_id)
|
97
|
+
# This function is to get cache_status
|
98
|
+
url = "#{URL::BASE_URL}/purge/#{request_id}"
|
99
|
+
@req_obj.request("get", url, @req_obj.create_headers)
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_metadata_from_remote_url(remote_file_url)
|
103
|
+
if remote_file_url == ""
|
104
|
+
raise ArgumentError, "remote_file_url is required"
|
105
|
+
end
|
106
|
+
url = "#{URL::REMOTE_METADATA_FULL_URL}?url=#{remote_file_url}"
|
107
|
+
@req_obj.request("get", url, @req_obj.create_headers)
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_upload_options(options)
|
111
|
+
|
112
|
+
# Validates upload value, checks if params are valid,
|
113
|
+
# changes snake to camel case which is supported by
|
114
|
+
# ImageKit server
|
115
|
+
|
116
|
+
|
117
|
+
response_list = []
|
118
|
+
options.each do |key, val|
|
119
|
+
if VALID_UPLOAD_OPTIONS.include?(key.to_s)
|
120
|
+
if val.is_a?(Array)
|
121
|
+
val = val.join(",")
|
122
|
+
end
|
123
|
+
if val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
124
|
+
val = val.to_s
|
125
|
+
end
|
126
|
+
options[key] = val
|
127
|
+
else
|
128
|
+
return false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
request_formatter(options)
|
132
|
+
end
|
133
|
+
end
|