filestack 2.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.
- 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
|