cartodb/app/controllers/carto/api/data_import_presenter.rb
2020-06-15 10:58:47 +08:00

192 lines
8.7 KiB
Ruby

require 'uri'
require 'json'
module Carto
module Api
class DataImportPresenter
HTTP_RESPONSE_CODE_MESSAGES = {
"300" => "This usually means the file has been moved! Click on the link to get its new location.",
"301" => "This usually means the file has been moved! Click on the link to get its new location.",
"302" => "This usually means the file has been temporally moved! Click on the link to get its new location.",
"303" => "This usually means the file has been moved! Click on the link to get its new location.",
"307" => "This usually means the file has been temporally moved! Click on the link to get its new location.",
"400" => "This usually means CARTO did not perform the request properly.",
"401" => "This usually means CARTO is not authorized to retrieve this file. If you have authorization, " \
"download the file manually and upload it from your computer.",
"402" => "This usually means CARTO is not authorized to retrieve this file. If you have authorization, " \
"download the file manually and upload it from your computer.",
"403" => "This usually means CARTO is not authorized to retrieve this file. If you have authorization, " \
"download the file manually and upload it from your computer. Tip: Should you be using 'https' " \
"instead of 'http' in your URL?",
"404" => "This usually means no file was found at the specified URL.",
"405" => "This usually means CARTO could not negotiate the download with the file's provider. The " \
"provider is probably using a non standard method to serve this file.",
"407" => "This usually means CARTO is not authorized to retrieve this file as proxy authentication " \
"is required. If you can use the apropiate proxy, download the file manually and upload " \
"it from your computer.",
"408" => "This usually means a timeout request was produced. You may want to try again.",
"409" => "This usually means a confilict in the request was produced. You might want to try again.",
"410" => "This usually means the file specified is now longer available at this location.",
"411" => "This usually means CARTO did not perform the request properly. 'Content Length' header is missing.",
"412" => "This usually means CARTO could not negotiate the download with the file's provider. The " \
"provider is probably using a non standard method to serve this file.",
"413" => "This usually means the file provider is denying the download because the file is too large.",
"417" => "This usually means CARTO could not negotiate the download with the file's provider. The " \
"provider is probably using a non standard method to serve this file.",
"500" => "This usually means the file provider responded with an internal server error. They might " \
"be overloaded or having some down time. Try again later!",
"501" => "This usually means CARTO could not negotiate the download with the file's provider. The " \
"provider is probably using a non standard method to serve this file.",
"502" => "This usually means the file provider responded with a bad gateway error.",
"503" => "This usually means the file provider responded with an internal server error. They might " \
"be overloaded or having some down time. Try again later!",
"505" => "This usually means the file provider doesn't seem to support the HTTP version used in the " \
"transaction. The provider is probably using a non standard method to serve this file.",
"511" => "This usually means CARTO is not authorized to retrieve this file. If you have " \
"authorization, download the file manually and upload it from your computer." }
def initialize(data_import)
@data_import = data_import
end
def api_public_values
public_values.reject { |key|
NON_API_VISIBLE_ATTRIBUTES.include?(key)
}
end
private
PUBLIC_ATTRIBUTES = [
'id',
'user_id',
'table_id',
'data_type',
'table_name',
'state',
'error_code',
'queue_id',
'tables_created_count',
'synchronization_id',
'service_name',
'service_item_id',
'type_guessing',
'quoted_fields_guessing',
'content_guessing',
'server',
'host',
'upload_host',
'resque_ppid',
'create_visualization',
'visualization_id',
# String field containing a json, format:
# {
# twitter_credits: Integer
# }
# No automatic conversion coded
'user_defined_limits'
]
NON_API_VISIBLE_ATTRIBUTES = [
'service_item_id',
'service_name',
'server',
'host',
'upload_host',
'resque_ppid',
]
def public_values
values = Hash[PUBLIC_ATTRIBUTES.map{ |attribute| [attribute, @data_import.send(attribute)] }]
values.merge!('get_error_text' => get_error_text)
values.merge!('display_name' => display_name)
values.merge!('queue_id' => @data_import.id)
values.merge!(success: @data_import.success) if @data_import.final_state?
values.merge!(original_url: @data_import.original_url)
values.merge!(data_type: @data_import.data_type)
values.merge!(warnings: get_warnings)
values.merge!(is_raster: @data_import.is_raster?)
if !@data_import.http_response_code.nil? && !@data_import.http_response_code.start_with?('2')
values.merge!(http_response_code: @data_import.http_response_code)
values.merge!(http_response_code_message: get_http_response_code_message(@data_import.http_response_code))
end
values
end
def get_error_text
if @data_import.error_code.nil?
nil
else
@data_import.error_code.blank? ? CartoDB::IMPORTER_ERROR_CODES[99999] : CartoDB::IMPORTER_ERROR_CODES[@data_import.error_code]
end
end
def display_name
if @data_import.service_name == 'twitter_search'
extract_twitter_display_name(@data_import)
else
url = [@data_import.data_source, @data_import.service_item_id].compact.select { |s| s != '' }.first
display_name = url.nil? ? @data_import.id : extract_filename(url)
display_name || @data_import.id
end
rescue => e
CartoDB.notify_debug(
'Error extracting display name',
data_import_id: @data_import.id,
service_item_id: @data_import.service_item_id,
data_source: @data_import.data_source,
exception: e.inspect
)
@data_import.id
end
def extract_filename(url)
URI.decode(File.basename(URI.parse(URI.encode(url.strip)).path))
end
def extract_twitter_display_name(data_import)
"Tweets about '#{JSON.parse(data_import.service_item_id)['categories'].map { |c| c['terms'] }.join(', ')}'"
rescue => e
CartoDB.notify_debug('Error extracting Twitter import display name', { data_import_id: data_import.id, service_item_id: data_import.service_item_id, data_source: data_import.data_source })
"Twitter search #{data_import.id}"
end
def get_http_response_code_message(http_response_code)
return nil if http_response_code.nil?
message = HTTP_RESPONSE_CODE_MESSAGES[http_response_code]
if message.nil?
message = case http_response_code
when /^1/ then "This usually means more actions are required to download this file."
when /^2/ then "This usually means everything went fine while fetching the file."
when /^3/ then "This usually means an unknown redirection error has occured."
when /^4/ then "This usually means an unknown client error has occured."
when /^5/ then "This usually means an unknown server error has occured."
else "This is an unkown type of HTTP status code."
end
end
message
end
# All warnings should be parsed into a single Hash here
def get_warnings
warnings = {}
if !@data_import.rejected_layers.nil?
warnings.merge!(rejected_layers: @data_import.rejected_layers.split(','))
warnings.merge!(user_max_layers: @data_import.user.max_layers)
end
warnings.merge!(JSON.parse(@data_import.runner_warnings)) if !@data_import.runner_warnings.nil?
warnings.empty? ? nil : warnings
end
end
end
end