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.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ task :console do
9
+ exec 'irb -r filestack/filestack -I ./lib'
10
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'filestack/models/filelink'
2
+ require 'filestack/models/filestack_client'
3
+ require 'filestack/models/filestack_security'
4
+ require 'filestack/utils/utils'
5
+ require 'filestack/models/filestack_transform'
@@ -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