Files

194 lines
6.6 KiB
Ruby
Executable File

# frozen_string_literal: true
#
# (c) Copyright Ascensio System SIA 2025
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative '../configuration/configuration'
# Class responsible for converting documents using a document conversion service.
class ServiceConverter
@config_manager = ConfigurationManager.new
class << self
attr_reader :config_manager
end
@convert_timeout = ServiceConverter.config_manager.convertation_timeout
@document_converter_url = ServiceConverter.config_manager.document_server_converter_uri.to_s
# get the url of the converted file
def self.get_converted_data(
document_uri,
from_ext,
to_ext,
document_revision_id,
is_async,
file_pass,
lang = nil,
title = nil
)
from_ext = File.extname(document_uri).downcase if from_ext.nil? # get the current document extension
# get the current document name or uuid
title = File.basename(URI.parse(document_uri).path) if title.nil?
title = UUID.generate.to_s if title.nil?
# get the document key
document_revision_id = document_uri if document_revision_id.empty?
document_revision_id = generate_revision_id(document_revision_id)
payload = { # write all the conversion parameters to the payload
async: is_async ? true : false,
url: document_uri,
outputtype: to_ext.delete('.'),
filetype: from_ext.delete('.'),
title:,
key: document_revision_id,
password: file_pass,
region: lang
}
data = nil
begin
uri = URI.parse(@document_converter_url) # create the request url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
DocumentHelper.verify_ssl(@document_converter_url, http)
http.read_timeout = @convert_timeout
http.open_timeout = 5
req = Net::HTTP::Post.new(uri.request_uri) # create the post request
req.add_field('Accept', 'application/json') # set headers
req.add_field('Content-Type', 'application/json')
if JwtHelper.enabled? && JwtHelper.use_for_request # if the signature is enabled
payload['token'] = JwtHelper.encode(payload) # get token and save it to the payload
jwt_header = ServiceConverter.config_manager.jwt_header; # get signature authorization header
# set it to the request with the Bearer prefix
req.add_field(jwt_header, "Bearer #{JwtHelper.encode({ payload: })}")
end
req.body = payload.to_json
res = http.request(req) # get the response
status_code = Integer(res.code, 10)
raise("Conversion service returned status: #{status_code}") if status_code != 200 # checking status code
data = res.body # and take its body
rescue Timeout::Error
# try again
rescue StandardError => e
raise(e.message)
end
json_data = JSON.parse(data) # parse response body
get_response_data(json_data) # get response url
end
# generate the document key value
def self.generate_revision_id(expected_key)
require('zlib')
if expected_key.length > 20 # check if the expected key length is greater than 20
# calculate 32-bit crc value from the expected key and turn it into the string
expected_key = Zlib.crc32(expected_key).to_s
end
key = expected_key.gsub(/[^0-9a-zA-Z.=]/, '_')
key[(key.length - [key.length, 20].min)..key.length] # the resulting key is of the length 20 or less
end
# create an error message for the error code
def self.process_convert_service_responce_error(error_code)
error_message = 'unknown error'
# add an error message to the error message template depending on the error code
case error_code
when -9
error_message = 'Error occurred in the ConvertService: Error conversion output format'
when -8
error_message = 'Error occurred in the ConvertService: Error document VKey'
when -7
error_message = 'Error occurred in the ConvertService: Error document request'
when -6
error_message = 'Error occurred in the ConvertService: Error database'
when -5
error_message = 'Error occurred in the ConvertService: Incorrect password'
when -4
error_message = 'Error occurred in the ConvertService: Error download error'
when -3
error_message = 'Error occurred in the ConvertService: Error convertation error'
when -2
error_message = 'Error occurred in the ConvertService: Error convertation timeout'
when -1
error_message = 'Error occurred in the ConvertService: Error convertation unknown'
when 0
# public const int c_nErrorNo = 0
else
error_message = "ErrorCode = #{error_code}" # default value for the error message
end
raise(error_message)
end
# get the response url
def self.get_response_data(json_data)
file_result = json_data
error_element = file_result['error']
unless error_element.nil? # if an error occurs
process_convert_service_responce_error(Integer(error_element)) # get an error message
end
is_end_convert = file_result['endConvert'] # check if the conversion is completed
result_percent = 0 # the conversion percentage
response_uri = ''
response_file_type = ''
if is_end_convert # if the conversion is completed
file_url_element = file_result['fileUrl']
file_type_element = file_result['fileType']
if file_url_element.nil? # and the file url doesn't exist
raise('Invalid answer format') # get ann error message
end
response_uri = file_url_element # otherwise, get the file url
response_file_type = file_type_element # get the file type
result_percent = 100
else # if the conversion isn't completed
percent_element = file_result['percent'] # get the percentage value
result_percent = unless percent_element.nil?
if percent_element.is_a?(String)
Integer(percent_element, 10)
else
Integer(percent_element)
end
end
result_percent = 99 if result_percent >= 100
end
[result_percent, response_uri, response_file_type]
end
end