lib/wolf_core/utils/file_utils.rb
require 'tempfile'
require_relative "logging_utils"
require_relative "string_utils"
module WolfCore
module FileUtils
extend WolfCore::LoggingUtils
extend WolfCore::StringUtils
module_function
def require_relative_folder(*folders)
folder_files = File.join(*folders, "**", "*.rb")
files_to_require = Dir[folder_files].sort
# log_object files_to_require, title: 'Files to require are'
safe_require(files_to_require)
end
def safe_require(missing_files)
error_counter = {}
while missing_files.any?
files_to_require = missing_files
missing_files = []
files_to_require.each do |file|
# log_object "Requiring file: #{file}"
require_relative file
rescue NameError => e
error_counter[file] = error_counter[file].to_i + 1
if error_counter[file] >= 10
log_object "Error requiring file: #{file}"
log_object e, title: "Error is"
log_object e.backtrace, title: "Error backtrace is"
end
missing_files << file if error_counter[file] < 15
end
end
end
def delete_files(*args)
pattern = File.join(*args)
files_to_delete = Dir.glob(pattern)
files_to_delete.each do |file|
File.delete(file)
log_object "File deleted: #{file}"
end
log_object "File Deleting Process Finished! (#{files_to_delete.size} files deleted)"
end
def encode_file_to_base64_from_url(url, headers: {})
uri, response = download_file_from_url(url, headers: headers).values_at(:uri, :response)
bytes = response.body
encoded_file = Base64.strict_encode64(bytes)
filename = filename_from_response(response, uri)
log_object filename, title: "filename is"
{ filename: filename, encoded_file: encoded_file }
rescue StandardError => e
raise_service_error({
message: "Failed to encode file url",
encode_file_error: { message: e.message, backtrace: e.backtrace },
url: url
})
end
def download_file_from_url(url, headers: {})
uri = URI.parse(url)
request = Net::HTTP::Get.new(uri)
headers.each { |key, value| request[key] = value }
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
raise_service_error({ message: "Failed to download file", url: url }) unless response.is_a?(Net::HTTPSuccess)
{ uri: uri, response: response }
end
def bytes_from_url(url, headers: {})
uri, response = download_file_from_url(url, headers: headers).values_at(:uri, :response)
bytes = response.body
filename = filename_from_response(response, uri)
{ bytes: bytes, filename: filename }
end
def filename_from_response(response, uri)
content_disposition = response["content-disposition"]
if content_disposition
match = content_disposition.match(/filename="?([^"]+)"?/)
match ? match[1] : File.basename(uri.path)
else
File.basename(uri.path)
end
end
def generate_url_from_file(file:, api_key:)
url = URI.parse("https://www.filestackapi.com/api/store/S3?key=#{api_key}")
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/octet-stream"
request.body = bytes_from_file(file)
response = Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
http.request(request)
end
parse_json_error = nil
if response.is_a?(Net::HTTPSuccess)
begin
response_body = JSON.parse(response.body)
rescue => e
parse_json_error = {
message: e.message,
backtrace: e.backtrace,
}
end
return response_body['url'] if response_body['url'].present?
end
raise_service_error({
message: "Failed to generate url from file",
url: url,
file: file,
request: request,
response: response,
response_body: response.body,
parse_json_error: parse_json_error,
})
end
def bytes_from_file(file)
if file.is_a?(ActionDispatch::Http::UploadedFile)
file.read
elsif base64_encoded?(file)
base64_string_to_bytes(file)
else
raise_service_error({
message: "Can not generate bytes from this file",
file: file,
})
end
end
def base64_string_to_bytes(base64_string)
begin
bytes = Base64.strict_decode64(base64_string)
bytes
rescue ArgumentError
raise_service_error({ message: 'Failed to decode base64 string', base64_string: base64_string })
end
end
def create_tempfile(filename, bytes)
temp_file = Tempfile.new([File.basename(filename, ".*"), File.extname(filename)])
temp_file.binmode
temp_file.write(bytes)
temp_file.rewind
temp_file
end
end
end