Class: SkylabStudio::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/skylab_studio/client.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Client

—————————— Instance Methods ——————————



31
32
33
34
35
# File 'lib/skylab_studio/client.rb', line 31

def initialize(options = {})
  settings = SkylabStudio::Client.configuration.settings.merge(options)

  @configuration = SkylabStudio::Config.new(settings)
end

Instance Attribute Details

#configurationObject (readonly)

Attributes



17
18
19
# File 'lib/skylab_studio/client.rb', line 17

def configuration
  @configuration
end

Class Method Details

.configurationObject

—————————— Class Methods ——————————



21
22
23
# File 'lib/skylab_studio/client.rb', line 21

def self.configuration
  @configuration ||= SkylabStudio::Config.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



25
26
27
# File 'lib/skylab_studio/client.rb', line 25

def self.configure
  yield configuration if block_given?
end

Instance Method Details

#cancel_job(job_id) ⇒ Object



82
83
84
85
86
# File 'lib/skylab_studio/client.rb', line 82

def cancel_job(job_id)
  validate_argument_presence nil, :job_id

  SkylabStudio::Request.new(@configuration).post("jobs/#{job_id}/cancel", nil)
end

#create_job(options = {}) ⇒ Object



41
42
43
44
45
46
# File 'lib/skylab_studio/client.rb', line 41

def create_job(options = {})
  validate_argument_presence options, :name
  validate_argument_presence options, :profile_id

  SkylabStudio::Request.new(@configuration).post(:jobs, options)
end

#create_profile(options = {}) ⇒ Object



92
93
94
95
96
# File 'lib/skylab_studio/client.rb', line 92

def create_profile(options = {})
  validate_argument_presence options, :name

  SkylabStudio::Request.new(@configuration).post(:profiles, options)
end

#delete_job(job_id) ⇒ Object



76
77
78
79
80
# File 'lib/skylab_studio/client.rb', line 76

def delete_job(job_id)
  validate_argument_presence nil, :job_id

  SkylabStudio::Request.new(@configuration).delete("jobs/#{job_id}")
end

#delete_photo(photo_id) ⇒ Object



134
135
136
137
138
# File 'lib/skylab_studio/client.rb', line 134

def delete_photo(photo_id)
  validate_argument_presence nil, :photo_id

  SkylabStudio::Request.new(@configuration).delete("photos/#{photo_id}")
end

#download_all_photos(photos_list, profile, output_path) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/skylab_studio/client.rb', line 192

def download_all_photos(photos_list, profile, output_path)
  raise 'Invalid output path' unless Dir.exist?(output_path)

  success_photos = []
  errored_photos = []
  bgs = []

  begin
    profile = get_profile(profile['id'])
    bgs = download_bg_images(profile) if profile && profile['photos']&.any?

    photo_ids = photos_list.map { |photo| photo['id'].to_s }.compact

    pool = Concurrent::FixedThreadPool.new(@configuration.settings[:max_download_concurrency])
    download_tasks = []
    photo_options = { return_on_error: true, bgs: bgs }
    photo_ids.each do |photo_id|
      download_tasks << Concurrent::Future.execute(executor: pool) do
        download_photo(photo_id.to_i, output_path, profile: profile, options: photo_options)
      end
    end

    # Wait for all download tasks to complete
    results = download_tasks.map(&:value)
    results.each do |result|
      if result[1]
        success_photos << result[0]
      else
        errored_photos << result[0]
      end
    end

    { success_photos: success_photos, errored_photos: errored_photos }
  rescue StandardError => e
    warn e

    { success_photos: success_photos, errored_photos: errored_photos }
  end
end

#download_photo(photo_id, output_path, profile: nil, options: {}) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/skylab_studio/client.rb', line 140

def download_photo(photo_id, output_path, profile: nil, options: {})
  file_name = ''

  unless Dir.exist?(output_path)
    # Must be a file path - separate output_path and file_name
    file_name = File.basename(output_path)
    output_path = File.dirname(output_path) || ''
  end

  begin
    photo = get_photo(photo_id)
    profile_id = photo['job']['profileId']

    file_name = photo['name'] if file_name.empty?

    profile ||= get_profile(profile_id)

    is_extract = profile['enableExtract'].to_s == 'true'
    replace_background = profile['replaceBackground'].to_s == 'true'
    is_dual_file_output = profile['dualFileOutput'].to_s == 'true'
    profile['enableStripPngMetadata'].to_s
    bgs = options[:bgs]

    # Load output image
    image_buffer = download_image_async(photo['retouchedUrl'])
    image = Vips::Image.new_from_buffer(image_buffer, '')

    if is_extract # Output extract image
      png_file_name = "#{File.basename(file_name, '.*')}.png"

      # Dual File Output will provide an image in the format specified in the outputFileType field
      # and an extracted image as a PNG.
      image.write_to_file(File.join(output_path, png_file_name)) if is_dual_file_output

      download_replaced_background_image(file_name, image, output_path, profile: profile, bgs: bgs) if replace_background

      # Regular Extract output
      image.write_to_file(File.join(output_path, png_file_name)) unless is_dual_file_output || replace_background
    else # Non-extracted regular image output
      image.write_to_file(File.join(output_path, file_name))
    end

    puts "Successfully downloaded: #{file_name}"
    [file_name, true]
  rescue StandardError => e
    error_msg = "Failed to download photo id: #{photo_id} - #{e}"
    raise error_msg if options[:return_on_error].nil?

    [file_name, false]
  end
end

#fetch_jobs_in_front(job_id) ⇒ Object



72
73
74
# File 'lib/skylab_studio/client.rb', line 72

def fetch_jobs_in_front(job_id)
  SkylabStudio::Request.new(@configuration).get("jobs/#{job_id}/jobs_in_front")
end

#get_job(job_id) ⇒ Object



48
49
50
51
52
# File 'lib/skylab_studio/client.rb', line 48

def get_job(job_id)
  validate_argument_presence nil, :job_id

  SkylabStudio::Request.new(@configuration).get("jobs/#{job_id}")
end

#get_job_by_name(options = {}) ⇒ Object



54
55
56
57
58
# File 'lib/skylab_studio/client.rb', line 54

def get_job_by_name(options = {})
  validate_argument_presence options, :name

  SkylabStudio::Request.new(@configuration).get('jobs/find_by_name', options)
end

#get_job_photos(job_id) ⇒ Object



130
131
132
# File 'lib/skylab_studio/client.rb', line 130

def get_job_photos(job_id)
  SkylabStudio::Request.new(@configuration).get('photos/list_for_job', { job_id: job_id })
end

#get_photo(photo_id) ⇒ Object



124
125
126
127
128
# File 'lib/skylab_studio/client.rb', line 124

def get_photo(photo_id)
  validate_argument_presence nil, :photo_id

  SkylabStudio::Request.new(@configuration).get("photos/#{photo_id}")
end

#get_profile(profile_id) ⇒ Object



98
99
100
101
102
# File 'lib/skylab_studio/client.rb', line 98

def get_profile(profile_id)
  validate_argument_presence nil, :profile_id

  SkylabStudio::Request.new(@configuration).get("profiles/#{profile_id}")
end

#list_jobsObject



37
38
39
# File 'lib/skylab_studio/client.rb', line 37

def list_jobs()
  SkylabStudio::Request.new(@configuration).get(:jobs)
end

#list_profiles(options = {}) ⇒ Object



88
89
90
# File 'lib/skylab_studio/client.rb', line 88

def list_profiles(options = {})
  SkylabStudio::Request.new(@configuration).get(:profiles, options)
end

#queue_job(options = {}) ⇒ Object



66
67
68
69
70
# File 'lib/skylab_studio/client.rb', line 66

def queue_job(options = {})
  validate_argument_presence options, :id

  SkylabStudio::Request.new(@configuration).post("jobs/#{options[:id]}/queue", options)
end

#update_job(job_id, options = {}) ⇒ Object



60
61
62
63
64
# File 'lib/skylab_studio/client.rb', line 60

def update_job(job_id, options = {})
  validate_argument_presence nil, :job_id

  SkylabStudio::Request.new(@configuration).patch("jobs/#{job_id}", options)
end

#update_profile(profile_id, options = {}) ⇒ Object



104
105
106
107
108
# File 'lib/skylab_studio/client.rb', line 104

def update_profile(profile_id, options = {})
  validate_argument_presence nil, :profile_id

  SkylabStudio::Request.new(@configuration).patch("profiles/#{profile_id}", options)
end

#upload_job_photo(photo_path = nil, job_id = nil) ⇒ Object



110
111
112
113
114
115
# File 'lib/skylab_studio/client.rb', line 110

def upload_job_photo(photo_path = nil, job_id = nil)
  validate_argument_presence nil, job_id
  validate_argument_presence nil, photo_path

  upload_photo(photo_path, job_id, 'job')
end

#upload_profile_photo(photo_path = nil, profile_id = nil) ⇒ Object



117
118
119
120
121
122
# File 'lib/skylab_studio/client.rb', line 117

def upload_profile_photo(photo_path = nil, profile_id = nil)
  validate_argument_presence nil, :photo_path
  validate_argument_presence nil, :profile_id

  upload_photo(photo_path, profile_id, 'profile')
end

#validate_hmac_headers(secret_key, job_json_string, request_timestamp, signature) ⇒ Object



232
233
234
235
236
237
238
239
240
241
# File 'lib/skylab_studio/client.rb', line 232

def validate_hmac_headers(secret_key, job_json_string, request_timestamp, signature)
  message = "#{request_timestamp}:#{job_json_string}".encode('utf-8')

  # Create the HMAC signature using SHA-256
  hmac_digest = OpenSSL::HMAC.digest('sha256', secret_key.encode('utf-8'), message)
  generated_sig = Base64.strict_encode64(hmac_digest).force_encoding('utf-8')

  # Compare the provided signature with the generated signature
  signature == generated_sig
end