filestack 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +98 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +201 -0
- data/README.md +148 -0
- data/Rakefile +10 -0
- data/VERSION +1 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/filestack-ruby.gemspec +33 -0
- data/lib/filestack.rb +5 -0
- data/lib/filestack/config.rb +36 -0
- data/lib/filestack/mixins/filestack_common.rb +93 -0
- data/lib/filestack/models/filelink.rb +89 -0
- data/lib/filestack/models/filestack_av.rb +32 -0
- data/lib/filestack/models/filestack_client.rb +55 -0
- data/lib/filestack/models/filestack_security.rb +82 -0
- data/lib/filestack/models/filestack_transform.rb +112 -0
- data/lib/filestack/ruby/version.rb +5 -0
- data/lib/filestack/utils/multipart_upload_utils.rb +223 -0
- data/lib/filestack/utils/utils.rb +107 -0
- metadata +168 -0
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "filestack/ruby"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
puts lib
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "filestack/ruby/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "filestack"
|
9
|
+
spec.version = Filestack::Ruby::VERSION
|
10
|
+
spec.authors = ["Filestack"]
|
11
|
+
spec.email = ["dev@filestack.com"]
|
12
|
+
|
13
|
+
spec.summary = %q{Official Ruby SDK for the Filestack API}
|
14
|
+
spec.description = %q{This is the official Ruby SDK for Filestack - API and content management system that makes it easy to add powerful file uploading and transformation capabilities to any web or mobile application.}
|
15
|
+
spec.homepage = "https://github.com/filestack/filestack-ruby"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features|test-files)/})
|
20
|
+
end
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "unirest", "~> 1.1.2"
|
26
|
+
spec.add_dependency "parallel", "~> 1.11.2"
|
27
|
+
spec.add_dependency "mimemagic", "~> 0.3.2"
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.15"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
32
|
+
spec.add_development_dependency "simplecov", "~> 0.14"
|
33
|
+
end
|
data/lib/filestack.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'filestack/ruby/version'
|
2
|
+
|
3
|
+
include Filestack
|
4
|
+
|
5
|
+
class FilestackConfig
|
6
|
+
API_URL = 'https://www.filestackapi.com/api'.freeze
|
7
|
+
CDN_URL = 'https://cdn.filestackcontent.com'.freeze
|
8
|
+
PROCESS_URL = 'https://process.filestackapi.com'.freeze
|
9
|
+
|
10
|
+
MULTIPART_START_URL = 'https://upload.filestackapi.com/multipart/start'.freeze
|
11
|
+
MULTIPART_UPLOAD_URL = 'https://upload.filestackapi.com/multipart/upload'.freeze
|
12
|
+
MULTIPART_COMPLETE_URL = 'https://upload.filestackapi.com/multipart/complete'.freeze
|
13
|
+
|
14
|
+
MULTIPART_PARAMS = %w[
|
15
|
+
store_location store_region store_container
|
16
|
+
store_path store_access
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
DEFAULT_CHUNK_SIZE = 5 * 1024**2
|
20
|
+
VERSION = Filestack::Ruby::VERSION
|
21
|
+
HEADERS = {
|
22
|
+
'User-Agent' => "filestack-ruby #{VERSION}",
|
23
|
+
'Filestack-Source' => "Ruby-#{VERSION}"
|
24
|
+
}.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
class TransformConfig
|
28
|
+
TRANSFORMATIONS = %w[
|
29
|
+
resize crop rotate flip flop watermark detect_faces
|
30
|
+
crop_faces pixelate_faces round_corners vignette polaroid
|
31
|
+
torn_edges shadow circle border sharpen blur monochrome
|
32
|
+
blackwhite sepia pixelate oil_paint negative modulate
|
33
|
+
partial_pixelate partial_blur collage upscale enhance
|
34
|
+
redeye ascii filetype_conversion quality
|
35
|
+
].freeze
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'filestack/config'
|
2
|
+
require 'filestack/utils/utils'
|
3
|
+
require 'filestack/utils/multipart_upload_utils'
|
4
|
+
require 'mimemagic'
|
5
|
+
|
6
|
+
# Module is mixin for common functionalities that all Filestack
|
7
|
+
# objects can call.
|
8
|
+
module FilestackCommon
|
9
|
+
include UploadUtils
|
10
|
+
# Get the contents of a Filestack handle
|
11
|
+
#
|
12
|
+
# @param [String] file_handle The Filelink handle
|
13
|
+
# @param [FilestackSecurity] security Optional Filestack security object
|
14
|
+
# if security is enabled
|
15
|
+
#
|
16
|
+
# @return [Bytes]
|
17
|
+
def send_get_content(url, parameters: nil)
|
18
|
+
UploadUtils.make_call(url, 'get', parameters: parameters)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get the content of a filehandle
|
22
|
+
#
|
23
|
+
# @param [String] filepath Local path of file to be written
|
24
|
+
#
|
25
|
+
# @return [Int] Size of file written
|
26
|
+
def send_download(filepath)
|
27
|
+
content = send_get_content(url)
|
28
|
+
File.write(filepath, content.body)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Send the delete api request to delete a filelink
|
32
|
+
#
|
33
|
+
# @param [String] url The url of the Filehandle
|
34
|
+
# to be deleted (includes security)
|
35
|
+
#
|
36
|
+
# @return [unirest::Response]
|
37
|
+
def send_delete(handle, apikey, security)
|
38
|
+
return 'Delete requires security' if security.nil?
|
39
|
+
signature = security.signature
|
40
|
+
policy = security.policy
|
41
|
+
base = "#{FilestackConfig::API_URL}/file"
|
42
|
+
UploadUtils.make_call(
|
43
|
+
"#{base}/#{handle}?key=#{apikey}&signature=#{signature}&policy=#{policy}",
|
44
|
+
'delete'
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Send the overwrite api request to update a filelink
|
49
|
+
#
|
50
|
+
# @param [String] filepath Filepath of file to upload
|
51
|
+
# @param [String] handle The Filelink handle
|
52
|
+
# @param [String] apikey Filestack API Key
|
53
|
+
# @param [FilestackSecurity] security Filestack security object
|
54
|
+
#
|
55
|
+
# @return [Typhoeus::Response]
|
56
|
+
def send_overwrite(filepath, handle, apikey, security)
|
57
|
+
return 'Overwrite requires security' if security.nil?
|
58
|
+
|
59
|
+
file = File.open(filepath, 'r')
|
60
|
+
mimetype = MimeMagic.by_magic(file)
|
61
|
+
content = file.read
|
62
|
+
|
63
|
+
signature = security.signature
|
64
|
+
policy = security.policy
|
65
|
+
|
66
|
+
headers = { 'Content-Type' => mimetype }
|
67
|
+
base = "#{FilestackConfig::API_URL}/file"
|
68
|
+
|
69
|
+
UploadUtils.make_call(
|
70
|
+
"#{base}/#{handle}?key=#{apikey}&signature=#{signature}&policy=#{policy}",
|
71
|
+
'put',
|
72
|
+
headers: headers,
|
73
|
+
parameters: content
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get tags or sfw content from a filelink
|
78
|
+
#
|
79
|
+
# @param [String] task 'tags' or 'sfw'
|
80
|
+
# @param [String] handle The filehandle
|
81
|
+
# @param [Filestack::Security] security Security object
|
82
|
+
#
|
83
|
+
# @return [Hash]
|
84
|
+
def send_tags(task, handle, security)
|
85
|
+
raise 'You must use security for tags' if security.nil?
|
86
|
+
|
87
|
+
policy = security.policy
|
88
|
+
signature = security.signature
|
89
|
+
url = "#{FilestackConfig::CDN_URL}/#{task}/"\
|
90
|
+
"security=signature:#{signature},policy:#{policy}/#{handle}"
|
91
|
+
UploadUtils.make_call(url, 'get').body[task]
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'filestack/ruby/version'
|
2
|
+
require 'filestack/config'
|
3
|
+
require 'filestack/utils/utils'
|
4
|
+
require 'filestack/models/filestack_transform'
|
5
|
+
require 'filestack/mixins/filestack_common'
|
6
|
+
|
7
|
+
# This class represents a file stored on your Filestack
|
8
|
+
# storage. Once initialized, you may perform transformations, conversions,
|
9
|
+
# get metadata, update, or delete it.
|
10
|
+
class Filelink
|
11
|
+
include FilestackCommon
|
12
|
+
include UploadUtils
|
13
|
+
attr_reader :handle, :apikey, :security
|
14
|
+
|
15
|
+
# Initialize Filelink
|
16
|
+
#
|
17
|
+
# @param [String] file_handle The Filelink handle
|
18
|
+
# @param [String] apikey Your Filestack API Key (optional)
|
19
|
+
# @param [FilestackSecurity] security Filestack security object, if
|
20
|
+
# security is enabled.
|
21
|
+
def initialize(handle, apikey: nil, security: nil)
|
22
|
+
@handle = handle
|
23
|
+
@apikey = apikey
|
24
|
+
@security = security
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get content of filelink
|
28
|
+
#
|
29
|
+
# @return [Bytes]
|
30
|
+
def get_content
|
31
|
+
send_get_content(url)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Download Filelink
|
35
|
+
#
|
36
|
+
# @param [String] filepath The local destination of the
|
37
|
+
# downloaded filelink
|
38
|
+
# @return [Unirest::Response]
|
39
|
+
def download(filepath)
|
40
|
+
send_download(filepath)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Delete filelink
|
44
|
+
#
|
45
|
+
# @return [Unirest::Response]
|
46
|
+
def delete
|
47
|
+
send_delete(handle, apikey, security)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Ovewrite filelink by uploading local file
|
51
|
+
#
|
52
|
+
# @param [String] filepath filepath of file to upload
|
53
|
+
#
|
54
|
+
# @return [Unirest::Response]
|
55
|
+
def overwrite(filepath)
|
56
|
+
send_overwrite(filepath, handle, apikey, security)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Turn the filelink into a transform object to perform
|
60
|
+
# transform operations
|
61
|
+
#
|
62
|
+
# @return [Filestack::Transform]
|
63
|
+
def transform
|
64
|
+
Transform.new(handle: @handle, apikey: @apikey, security: @security)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return auto and user tags for the filelink
|
68
|
+
#
|
69
|
+
# @return [Hash]
|
70
|
+
def tags
|
71
|
+
send_tags('tags', @handle, @security)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return true (SFW) or false (NSFW)
|
75
|
+
#
|
76
|
+
# @return [Bool]
|
77
|
+
def sfw
|
78
|
+
send_tags('sfw', @handle, @security)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Get the URL of the Filelink
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def url
|
85
|
+
UploadUtils.get_url(
|
86
|
+
FilestackConfig::CDN_URL, handle: handle, security: security
|
87
|
+
)
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'filestack/models/filelink'
|
2
|
+
require 'filestack/utils/utils'
|
3
|
+
|
4
|
+
# Class for AV objects -- allows to check status
|
5
|
+
# and upgrade to filelink once completed
|
6
|
+
class AV
|
7
|
+
include UploadUtils
|
8
|
+
attr_reader :apikey, :security
|
9
|
+
|
10
|
+
def initialize(url, apikey: nil, security: nil)
|
11
|
+
@url = url
|
12
|
+
@apikey = apikey
|
13
|
+
@security = security
|
14
|
+
end
|
15
|
+
|
16
|
+
# Turns AV into filelink if video conversion is complete
|
17
|
+
#
|
18
|
+
# @return [Filestack::Filelink]
|
19
|
+
def to_filelink
|
20
|
+
return 'Video conversion incomplete' unless status == 'completed'
|
21
|
+
response = UploadUtils.make_call(@url, 'get').body
|
22
|
+
handle = response['data']['url'].split('/').last
|
23
|
+
Filelink.new(handle, apikey: @apikey, security: @security)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Checks the status of the video conversion
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
def status
|
30
|
+
UploadUtils.make_call(@url, 'get').body['status']
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'filestack/utils/multipart_upload_utils'
|
2
|
+
require 'filestack/models/filestack_transform'
|
3
|
+
require 'filestack/utils/utils'
|
4
|
+
require './lib/filestack/'
|
5
|
+
|
6
|
+
# The Filestack Client class acts as a hub for all
|
7
|
+
# Filestack actions that do not require a file handle, including
|
8
|
+
# uploading files (both local and external), initiating an external
|
9
|
+
# transformation, and other tasks
|
10
|
+
class Client
|
11
|
+
include MultipartUploadUtils
|
12
|
+
include UploadUtils
|
13
|
+
attr_reader :apikey, :security
|
14
|
+
|
15
|
+
# Initialize Client
|
16
|
+
#
|
17
|
+
# @param [String] apikey Your Filestack API key
|
18
|
+
# @param [FilestackSecurity] security A Filestack security object,
|
19
|
+
# if security is enabled
|
20
|
+
def initialize(apikey, security: nil)
|
21
|
+
@apikey = apikey
|
22
|
+
@security = security
|
23
|
+
end
|
24
|
+
|
25
|
+
# Upload a local file or external url
|
26
|
+
# @param [String] filepath The path of a local file
|
27
|
+
# @param [String] external_url An external URL
|
28
|
+
# @param [Bool] multipart Switch for miltipart
|
29
|
+
# (Default: true)
|
30
|
+
# @param [Hash] options User-supplied upload options
|
31
|
+
#
|
32
|
+
# return [Filestack::Filelink]
|
33
|
+
def upload(filepath: nil, external_url: nil, multipart: true, options: nil, storage: 's3')
|
34
|
+
if filepath && external_url
|
35
|
+
return 'You cannot upload a URL and file at the same time'
|
36
|
+
end
|
37
|
+
response = if filepath && multipart
|
38
|
+
multipart_upload(@apikey, filepath, @security, options)
|
39
|
+
else
|
40
|
+
send_upload(
|
41
|
+
@apikey,
|
42
|
+
filepath: filepath,
|
43
|
+
external_url: external_url,
|
44
|
+
options: options,
|
45
|
+
security: @security,
|
46
|
+
storage: storage
|
47
|
+
)
|
48
|
+
end
|
49
|
+
Filelink.new(response['handle'], security: @security, apikey: @apikey)
|
50
|
+
end
|
51
|
+
|
52
|
+
def transform_external(external_url)
|
53
|
+
Transform.new(external_url: external_url, security: @security, apikey: @apikey)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This class represents a Filestack Security object that you must passed
|
7
|
+
# in with your calls if your account has security enabled. You can manage
|
8
|
+
# your Filestack app's security and secret by logging into the Filestack
|
9
|
+
# Dev portal.
|
10
|
+
#
|
11
|
+
class FilestackSecurity
|
12
|
+
DEFAULT_EXPIRY = 3600
|
13
|
+
|
14
|
+
attr_accessor :policy, :signature
|
15
|
+
|
16
|
+
# Initialize FilestackSecurity object
|
17
|
+
#
|
18
|
+
# @param [String] secret Your filestack security secret
|
19
|
+
# @param [Hash] options Hash of options:
|
20
|
+
# call: The calls that you allow this policy to
|
21
|
+
# make, e.g convert, exif, pick, read, remove,
|
22
|
+
# stat, store, write, writeUrl
|
23
|
+
# container: (regex) store must match container
|
24
|
+
# that the files will be stored under
|
25
|
+
# expiry: (timestamp) epoch_timestamp expire,
|
26
|
+
# defaults to 1hr
|
27
|
+
# handle: specific file this policy can access
|
28
|
+
# maxSize: (number) maximum file size in bytes
|
29
|
+
# that can be stored by requests with policy
|
30
|
+
# minSize: (number) minimum file size in bytes
|
31
|
+
# that can be stored by requests with policy
|
32
|
+
# path: (regex) store must match the path that
|
33
|
+
# the files will be stored under.
|
34
|
+
# url: (regex) subset of external URL domains
|
35
|
+
# that are allowed to be image/document
|
36
|
+
# sources for processing
|
37
|
+
def initialize(secret, options: {})
|
38
|
+
generate(secret, options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Generate the security policy and signature given a string and options
|
42
|
+
#
|
43
|
+
# @param [String] secret Your filestack security secret
|
44
|
+
# @param [Hash] options Hash of options - see constructor
|
45
|
+
def generate(secret, options)
|
46
|
+
policy_json = create_policy_string(options)
|
47
|
+
@policy = Base64.urlsafe_encode64(policy_json)
|
48
|
+
@signature = OpenSSL::HMAC.hexdigest('sha256', secret, policy)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sign the URL by appending policy and signature URL parameters
|
52
|
+
#
|
53
|
+
# @param [String] url The URL to sign
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def sign_url(url)
|
57
|
+
format('%s&policy=%s&signature=%s', url, policy, signature)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
#
|
63
|
+
# Manage options and convert hash to json string
|
64
|
+
#
|
65
|
+
def create_policy_string(options)
|
66
|
+
options[:expiry] = expiry_timestamp(options)
|
67
|
+
options.to_json
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Get expiration timestamp by adding seconds in option or using default
|
72
|
+
#
|
73
|
+
def expiry_timestamp(options)
|
74
|
+
expiry_time = if options.key?(:expiry)
|
75
|
+
options[:expiry]
|
76
|
+
else
|
77
|
+
FilestackSecurity::DEFAULT_EXPIRY
|
78
|
+
end
|
79
|
+
|
80
|
+
Time.now.to_i + expiry_time
|
81
|
+
end
|
82
|
+
end
|