crowdin-api 1.2.0 → 1.4.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +102 -43
  3. data/README.md +37 -6
  4. data/bin/crowdin-console +1 -1
  5. data/crowdin-api.gemspec +1 -2
  6. data/lib/crowdin-api/api_resources/bundles.rb +81 -0
  7. data/lib/crowdin-api/{api-resources → api_resources}/dictionaries.rb +8 -10
  8. data/lib/crowdin-api/{api-resources → api_resources}/distributions.rb +25 -32
  9. data/lib/crowdin-api/{api-resources → api_resources}/glossaries.rb +64 -82
  10. data/lib/crowdin-api/{api-resources → api_resources}/labels.rb +28 -47
  11. data/lib/crowdin-api/api_resources/languages.rb +61 -0
  12. data/lib/crowdin-api/api_resources/machine_translation_engines.rb +79 -0
  13. data/lib/crowdin-api/api_resources/projects.rb +124 -0
  14. data/lib/crowdin-api/api_resources/reports.rb +120 -0
  15. data/lib/crowdin-api/{api-resources → api_resources}/screenshots.rb +47 -61
  16. data/lib/crowdin-api/{api-resources → api_resources}/source_files.rb +68 -131
  17. data/lib/crowdin-api/{api-resources → api_resources}/source_strings.rb +19 -24
  18. data/lib/crowdin-api/api_resources/storages.rb +54 -0
  19. data/lib/crowdin-api/{api-resources → api_resources}/string_comments.rb +18 -23
  20. data/lib/crowdin-api/{api-resources → api_resources}/string_translations.rb +64 -91
  21. data/lib/crowdin-api/{api-resources → api_resources}/tasks.rb +30 -41
  22. data/lib/crowdin-api/api_resources/teams.rb +135 -0
  23. data/lib/crowdin-api/{api-resources → api_resources}/translation_memory.rb +38 -52
  24. data/lib/crowdin-api/{api-resources → api_resources}/translation_status.rb +24 -30
  25. data/lib/crowdin-api/{api-resources → api_resources}/translations.rb +41 -58
  26. data/lib/crowdin-api/api_resources/users.rb +161 -0
  27. data/lib/crowdin-api/api_resources/vendors.rb +21 -0
  28. data/lib/crowdin-api/{api-resources → api_resources}/webhooks.rb +19 -24
  29. data/lib/crowdin-api/api_resources/workflows.rb +59 -0
  30. data/lib/crowdin-api/client/client.rb +134 -39
  31. data/lib/crowdin-api/client/configuration.rb +12 -12
  32. data/lib/crowdin-api/client/version.rb +1 -1
  33. data/lib/crowdin-api/core/errors.rb +1 -0
  34. data/lib/crowdin-api/core/errors_raisers.rb +1 -1
  35. data/lib/crowdin-api/core/fetch_all_extensions.rb +14 -0
  36. data/lib/crowdin-api/core/request.rb +50 -90
  37. data/lib/crowdin-api/core/send_request.rb +67 -0
  38. data/lib/crowdin-api.rb +18 -24
  39. data/spec/api_resources/bundles_spec.rb +61 -0
  40. data/spec/api_resources/dictionaries_spec.rb +23 -0
  41. data/spec/api_resources/distributions_spec.rb +71 -0
  42. data/spec/api_resources/glossaries_spec.rb +167 -0
  43. data/spec/api_resources/labels_spec.rb +71 -0
  44. data/spec/api_resources/languages_spec.rb +51 -0
  45. data/spec/api_resources/machine_translation_engines_spec.rb +63 -0
  46. data/spec/api_resources/projects_spec.rb +215 -0
  47. data/spec/api_resources/reports_spec.rb +95 -0
  48. data/spec/api_resources/screenshots_spec.rb +134 -0
  49. data/spec/api_resources/source_files_spec.rb +184 -0
  50. data/spec/api_resources/source_strings_spec.rb +51 -0
  51. data/spec/api_resources/storages_spec.rb +41 -0
  52. data/spec/api_resources/string_comments_spec.rb +51 -0
  53. data/spec/api_resources/string_translations_spec.rb +141 -0
  54. data/spec/api_resources/tasks_spec.rb +79 -0
  55. data/spec/api_resources/teams_spec.rb +100 -0
  56. data/spec/api_resources/translation_memory_spec.rb +114 -0
  57. data/spec/api_resources/translation_status_spec.rb +61 -0
  58. data/spec/api_resources/translations_spec.rb +107 -0
  59. data/spec/api_resources/users_spec.rb +117 -0
  60. data/spec/api_resources/vendors_spec.rb +13 -0
  61. data/spec/api_resources/webhooks_spec.rb +51 -0
  62. data/spec/api_resources/workflows_spec.rb +41 -0
  63. data/spec/spec_helper.rb +23 -2
  64. data/spec/unit/client_spec.rb +85 -0
  65. metadata +67 -43
  66. data/bin/setup +0 -6
  67. data/lib/crowdin-api/api-resources/languages.rb +0 -82
  68. data/lib/crowdin-api/api-resources/machine_translation_engines.rb +0 -74
  69. data/lib/crowdin-api/api-resources/projects.rb +0 -148
  70. data/lib/crowdin-api/api-resources/reports.rb +0 -138
  71. data/lib/crowdin-api/api-resources/storages.rb +0 -106
  72. data/lib/crowdin-api/api-resources/teams.rb +0 -144
  73. data/lib/crowdin-api/api-resources/users.rb +0 -129
  74. data/lib/crowdin-api/api-resources/vendors.rb +0 -21
  75. data/lib/crowdin-api/api-resources/workflows.rb +0 -62
  76. data/lib/crowdin-api/core/utils.rb +0 -10
  77. data/spec/client/client-instance_spec.rb +0 -14
  78. data/spec/client/configuration-instance_spec.rb +0 -72
@@ -7,26 +7,24 @@ module Crowdin
7
7
  project_id || raise_project_id_is_required_error
8
8
 
9
9
  request = Web::Request.new(
10
- self,
10
+ connection,
11
11
  :get,
12
- "/projects/#{project_id}/webhooks",
13
- query
12
+ "#{config.target_api_url}/projects/#{project_id}/webhooks",
13
+ { params: query }
14
14
  )
15
-
16
- request.perform
15
+ Web::SendRequest.new(request).perform
17
16
  end
18
17
 
19
18
  def add_webhook(query = {}, project_id = config.project_id)
20
19
  project_id || raise_project_id_is_required_error
21
20
 
22
21
  request = Web::Request.new(
23
- self,
22
+ connection,
24
23
  :post,
25
- "/projects/#{project_id}/webhooks",
26
- query
24
+ "#{config.target_api_url}/projects/#{project_id}/webhooks",
25
+ { params: query }
27
26
  )
28
-
29
- request.perform
27
+ Web::SendRequest.new(request).perform
30
28
  end
31
29
 
32
30
  def get_webhook(webhook_id = nil, project_id = config.project_id)
@@ -34,12 +32,11 @@ module Crowdin
34
32
  project_id || raise_project_id_is_required_error
35
33
 
36
34
  request = Web::Request.new(
37
- self,
35
+ connection,
38
36
  :get,
39
- "/projects/#{project_id}/webhooks/#{webhook_id}"
37
+ "#{config.target_api_url}/projects/#{project_id}/webhooks/#{webhook_id}"
40
38
  )
41
-
42
- request.perform
39
+ Web::SendRequest.new(request).perform
43
40
  end
44
41
 
45
42
  def delete_webhook(webhook_id = nil, project_id = config.project_id)
@@ -47,26 +44,24 @@ module Crowdin
47
44
  project_id || raise_project_id_is_required_error
48
45
 
49
46
  request = Web::Request.new(
50
- self,
47
+ connection,
51
48
  :delete,
52
- "/projects/#{project_id}/webhooks/#{webhook_id}"
49
+ "#{config.target_api_url}/projects/#{project_id}/webhooks/#{webhook_id}"
53
50
  )
54
-
55
- request.perform
51
+ Web::SendRequest.new(request).perform
56
52
  end
57
53
 
58
- def edit_screenshot(webhook_id = nil, query = {}, project_id = config.project_id)
54
+ def edit_webhook(webhook_id = nil, query = {}, project_id = config.project_id)
59
55
  webhook_id || raise_parameter_is_required_error(:webhook_id)
60
56
  project_id || raise_project_id_is_required_error
61
57
 
62
58
  request = Web::Request.new(
63
- self,
59
+ connection,
64
60
  :patch,
65
- "/projects/#{project_id}/webhooks/#{webhook_id}",
66
- query
61
+ "#{config.target_api_url}/projects/#{project_id}/webhooks/#{webhook_id}",
62
+ { params: query }
67
63
  )
68
-
69
- request.perform
64
+ Web::SendRequest.new(request).perform
70
65
  end
71
66
  end
72
67
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crowdin
4
+ module ApiResources
5
+ module Workflows
6
+ # -- For Enterprise mode only --
7
+
8
+ def list_workflow_steps(query = {}, project_id = config.project_id)
9
+ enterprise_mode? || raise_only_for_enterprise_mode_error
10
+ project_id || raise_project_id_is_required_error
11
+
12
+ request = Web::Request.new(
13
+ connection,
14
+ :get,
15
+ "#{config.target_api_url}/projects/#{project_id}/workflow-steps",
16
+ { params: query }
17
+ )
18
+ Web::SendRequest.new(request).perform
19
+ end
20
+
21
+ def get_workflow_step(step_id = nil, project_id = config.project_id)
22
+ enterprise_mode? || raise_only_for_enterprise_mode_error
23
+ step_id || raise_parameter_is_required_error(:step_id)
24
+ project_id || raise_project_id_is_required_error
25
+
26
+ request = Web::Request.new(
27
+ connection,
28
+ :get,
29
+ "#{config.target_api_url}/projects/#{project_id}/workflow-steps/#{step_id}"
30
+ )
31
+ Web::SendRequest.new(request).perform
32
+ end
33
+
34
+ def list_workflow_templates(query = {})
35
+ enterprise_mode? || raise_only_for_enterprise_mode_error
36
+
37
+ request = Web::Request.new(
38
+ connection,
39
+ :get,
40
+ "#{config.target_api_url}/workflow-templates",
41
+ { params: query }
42
+ )
43
+ Web::SendRequest.new(request).perform
44
+ end
45
+
46
+ def get_workflow_template(template_id = nil)
47
+ enterprise_mode? || raise_only_for_enterprise_mode_error
48
+ template_id || raise_parameter_is_required_error(:template_id)
49
+
50
+ request = Web::Request.new(
51
+ connection,
52
+ :get,
53
+ "#{config.target_api_url}/workflow-templates/#{template_id}"
54
+ )
55
+ Web::SendRequest.new(request).perform
56
+ end
57
+ end
58
+ end
59
+ end
@@ -20,76 +20,171 @@ module Crowdin
20
20
  # crowdin.list_projects
21
21
  #
22
22
  class Client
23
- extend Utils
24
-
25
- # API Resources modules
26
- API_RESOURCES_MODULES = %i[Storages Languages Projects Workflows SourceFiles Translations SourceStrings
27
- StringTranslations StringComments Screenshots Glossaries TranslationMemory
28
- MachineTranslationEngines Reports Tasks Users Teams Vendors Webhooks
29
- Dictionaries Distributions Labels TranslationStatus].freeze
30
-
31
- # Error Raisers modules
32
- ERROR_RAISERS_MODULES = %i[ApiErrorsRaiser ClientErrorsRaiser].freeze
33
-
34
- # Processing all API Resources modules to include them to the Client
23
+ # Processing API Resources modules to include them to the Client
35
24
  API_RESOURCES_MODULES.each do |module_name|
36
- Client.send(:include, fetch_module_full_name_from_string("Crowdin::ApiResources::#{module_name}"))
25
+ Client.send(:include, Object.const_get("Crowdin::ApiResources::#{module_name}"))
37
26
  end
38
27
 
39
- # Processing all Error Raisers modules to include them to the Client
28
+ # Processing Error Raisers modules to include them to the Client
40
29
  ERROR_RAISERS_MODULES.each do |module_name|
41
- Client.send(:include, fetch_module_full_name_from_string("Crowdin::Errors::#{module_name}"))
30
+ Client.send(:include, Object.const_get("Crowdin::Errors::#{module_name}"))
42
31
  end
43
32
 
33
+ include Web::FetchAllExtensions
34
+
35
+ # Config instance that includes configuration options for the Client
44
36
  attr_reader :config
37
+ # Instance with established connection through RestClient to the Crowdin API
45
38
  attr_reader :connection
39
+ # Instance with options and headers for RestClient connection
46
40
  attr_reader :options
41
+ # Logger instance
47
42
  attr_reader :logger
48
43
 
49
44
  def initialize(&block)
50
45
  build_configuration(&block)
51
46
 
52
- check_logger
53
- check_rest_client_proxy
47
+ update_logger
48
+ update_rest_client_proxy
54
49
 
55
50
  build_connection
56
51
  end
57
52
 
58
- def log!(message)
59
- !config.logger_enabled? || logger.debug(message)
53
+ def log(message)
54
+ !logger_enabled? || logger.debug(message)
60
55
  end
61
56
 
62
57
  def logger=(logger)
63
- raise_logger_are_not_enabled_error unless config.logger_enabled?
58
+ raise_logger_are_not_enabled_error unless logger_enabled?
59
+
64
60
  @logger = logger
61
+ update_rest_client_logger
65
62
  end
66
63
 
67
- private
68
-
69
- def build_configuration
70
- @config = Crowdin::Configuration.new
71
- yield config if block_given?
64
+ def enterprise_mode?
65
+ !!config.organization_domain
72
66
  end
73
67
 
74
- def build_connection
75
- @connection ||= ::RestClient::Resource.new(config.base_url, build_options)
68
+ def logger_enabled?
69
+ config.logger_enabled?
76
70
  end
77
71
 
78
- def build_options
79
- @options ||= config.options.merge(headers: config.headers)
72
+ #
73
+ # FetchAll options:
74
+ # * limit, Integer, default: 500 | How many records need to load per one request
75
+ # * offset, Integer, default: 0 | How many records need to skip
76
+ # * request_delay, Integer (seconds), default: 0 | Delay between requests
77
+ #
78
+ #
79
+ # Note: Please, specify project_id while Client initialization if you need to use methods that need it within FetchAll
80
+ #
81
+ # === Example
82
+ #
83
+ # @crowdin.fetch_all(:list_projects)
84
+ #
85
+ # with specified options
86
+ #
87
+ # @crowdin.fetch_all(:list_projects, { limit: 10, request_delay: 1 })
88
+ #
89
+ # playing with response per fetch. Note: the block actually don't make any effect to finite result
90
+ #
91
+ # @crowdin.fetch_all(:list_projects, { limit: 10, request_delay: 1 }) { |response| puts response['data'] }
92
+ #
93
+ # also you can specify retry configuration to handle some exceptions
94
+ #
95
+ # Retry configuration options:
96
+ # * request_delay, Integer (seconds), default: 0 | Delay between retries
97
+ # * retries_count, Integer, default: 0
98
+ # * error_messages, Array
99
+ #
100
+ # @crowdin.fetch_all(:list_projects, {}, { request_delay: 2, retries_count: 3, error_messages: ['401'] })
101
+ #
102
+ # fetch all execution will be terminated if response error are same as in error_messages array
103
+ # otherwise system will retry so many times, as indicated at tries_count
104
+ #
105
+ def fetch_all(api_resource, opts = {}, retry_opts = {})
106
+ unless Web::FetchAllExtensions::API_RESOURCES_FOR_FETCH_ALL.include?(api_resource)
107
+ raise(Errors::FetchAllProcessingError, "#{api_resource} method aren't supported for FetchAll")
108
+ end
109
+
110
+ limit = opts[:limit] || Web::FetchAllExtensions::MAX_ITEMS_COUNT_PER_REQUEST
111
+ offset = opts[:offset] || 0
112
+ request_delay = opts[:request_delay] || 0
113
+
114
+ retry_request_delay = retry_opts[:request_delay] || 0
115
+ retries_count = retry_opts[:retries_count] || 0
116
+ retry_error_messages = retry_opts[:error_messages] || []
117
+
118
+ result = []
119
+ loop do
120
+ response = case api_resource
121
+ when :list_terms
122
+ send(api_resource, opts[:glossary_id], { limit: limit, offset: offset }.merge(opts))
123
+ when :list_file_revisions
124
+ send(api_resource, opts[:file_id], { limit: limit, offset: offset }.merge(opts))
125
+ else
126
+ send(api_resource, { limit: limit, offset: offset }.merge(opts))
127
+ end
128
+
129
+ if response.is_a?(String) && response.match('Something went wrong')
130
+ if retries_count.positive?
131
+ retry_error_messages.each do |message|
132
+ break if response.match(message)
133
+ end
134
+
135
+ retries_count -= 1
136
+ sleep retry_request_delay
137
+ else
138
+ raise(Errors::FetchAllProcessingError, response)
139
+ end
140
+ else
141
+ yield response if block_given?
142
+ deserialized_response = response['data']
143
+ result.concat(deserialized_response)
144
+ offset += deserialized_response.size
145
+ break if deserialized_response.size < limit
146
+ end
147
+
148
+ sleep request_delay
149
+ end
150
+ result
151
+ rescue StandardError => e
152
+ raise(Errors::FetchAllProcessingError, "FetchAll wasn't processed. Details - #{e.message}")
80
153
  end
81
154
 
82
- def set_default_logger
83
- require 'logger'
84
- @logger ||= Logger.new($stderr)
85
- end
155
+ private
86
156
 
87
- def check_rest_client_proxy
88
- ENV['http_proxy'] ? ::RestClient.proxy = ENV['http_proxy'] : false
89
- end
157
+ def build_configuration
158
+ @config = Crowdin::Configuration.new
159
+ yield config if block_given?
160
+ end
90
161
 
91
- def check_logger
92
- config.logger_enabled? ? set_default_logger : config.enable_logger = false
93
- end
162
+ def build_connection
163
+ build_options
164
+ @connection ||= ::RestClient::Resource.new(config.base_url, options)
165
+ end
166
+
167
+ def build_options
168
+ @options ||= config.options.merge(headers: config.headers)
169
+ end
170
+
171
+ def set_default_logger
172
+ require 'logger'
173
+
174
+ @logger ||= Logger.new($stdout)
175
+ update_rest_client_logger
176
+ end
177
+
178
+ def update_rest_client_logger
179
+ ::RestClient.log = @logger
180
+ end
181
+
182
+ def update_rest_client_proxy
183
+ ENV['http_proxy'] ? ::RestClient.proxy = ENV.fetch('http_proxy') : false
184
+ end
185
+
186
+ def update_logger
187
+ config.logger_enabled? ? set_default_logger : config.enable_logger = false
188
+ end
94
189
  end
95
190
  end
@@ -5,12 +5,12 @@ module Crowdin
5
5
  attr_accessor :api_token
6
6
  attr_accessor :project_id
7
7
  attr_accessor :organization_domain
8
+
8
9
  attr_accessor :enable_logger
10
+ alias logger_enabled? enable_logger
9
11
 
10
12
  attr_reader :target_api_url
11
13
 
12
- alias logger_enabled? enable_logger
13
-
14
14
  def initialize
15
15
  @target_api_url = '/api/v2'
16
16
  end
@@ -33,16 +33,16 @@ module Crowdin
33
33
  end
34
34
 
35
35
  def base_url
36
- if enterprise_mode?
37
- organization_domain.include?('.com') ? organization_domain : "https://#{organization_domain}.api.crowdin.com"
38
- else
39
- 'https://api.crowdin.com'
40
- end
41
- end
42
-
43
- def organization_domain?
44
- !!organization_domain
36
+ @base_url ||=
37
+ if !!organization_domain
38
+ if organization_domain.include?('.com')
39
+ "https://#{organization_domain}"
40
+ else
41
+ "https://#{organization_domain}.api.crowdin.com"
42
+ end
43
+ else
44
+ 'https://api.crowdin.com'
45
+ end
45
46
  end
46
- alias enterprise_mode? organization_domain?
47
47
  end
48
48
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Crowdin
4
4
  class Client
5
- VERSION = '1.2.0'
5
+ VERSION = '1.4.0'
6
6
  end
7
7
  end
@@ -4,5 +4,6 @@ module Crowdin
4
4
  module Errors
5
5
  class OnlyForEnterpriseModeError < StandardError; end
6
6
  class LoggerAreNotEnabledError < StandardError; end
7
+ class FetchAllProcessingError < StandardError; end
7
8
  end
8
9
  end
@@ -6,7 +6,7 @@ module Crowdin
6
6
  module ClientErrorsRaiser
7
7
  def raise_logger_are_not_enabled_error
8
8
  raise(LoggerAreNotEnabledError, 'Logger are not enabled in your Client configuration, enable it ' \
9
- 'before setting your own logger')
9
+ 'before setting your logger')
10
10
  end
11
11
  end
12
12
 
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crowdin
4
+ module Web
5
+ module FetchAllExtensions
6
+ MAX_ITEMS_COUNT_PER_REQUEST = 500.freeze
7
+ API_RESOURCES_FOR_FETCH_ALL = %i[list_vendors list_dictionaries list_directories list_distributions
8
+ list_workflow_templates list_languages list_labels list_mts list_files
9
+ list_projects list_groups list_branches list_strings list_storages
10
+ list_string_comments list_tasks list_user_tasks list_webhooks
11
+ list_terms list_file_revisions list_bundles].freeze
12
+ end
13
+ end
14
+ end
@@ -3,116 +3,76 @@
3
3
  module Crowdin
4
4
  module Web
5
5
  class Request
6
- attr_reader :client
7
-
8
- def initialize(client, method, path, query = {}, headers = {}, destination = nil)
9
- @client = client
10
- @method = method
11
- @full_path = client.config.target_api_url + path
12
- @payload = perform_payload(query)
13
- @headers = headers
14
- @destination = destination
15
- @errors = []
6
+ attr_reader :connection
7
+ attr_reader :method
8
+ attr_reader :payload
9
+
10
+ def initialize(connection, method, url, payload = {})
11
+ @connection = connection[url]
12
+ @method = method
13
+ @payload = build_payload(payload)
16
14
  end
17
15
 
18
- def perform
19
- process_request!
20
- process_response!
16
+ def get?
17
+ method.eql?(:get)
21
18
  end
22
19
 
23
- private
24
-
25
- def process_request!
26
- return @response = client.connection[@full_path].delete if delete_request?
27
- return @response = client.connection[@full_path].get(@payload) if get_request?
28
-
29
- client.connection[@full_path].send(@method, @payload, @headers) { |response, _, _| @response = response }
30
- rescue StandardError => error
31
- client.log! error
32
-
33
- @errors << "Something went wrong while request proccessing. Details - #{error.class}"
20
+ def get
21
+ connection.get(prepare_payload(payload[:params]))
34
22
  end
35
23
 
36
- def process_response!
37
- return fetch_errors if @errors.any?
38
-
39
- begin
40
- if @response
41
- client.log! "args: #{@response.request.args}"
42
-
43
- if @response.body.empty?
44
- @response.code
45
- else
46
- doc = JSON.parse(@response.body)
47
-
48
- client.log! "body: #{doc}"
49
-
50
- data = fetch_response_data(doc)
51
-
52
- @errors.any? ? fetch_errors : data
53
- end
54
- end
55
- rescue StandardError => error
56
- client.log! error
57
-
58
- @errors << "Something went wrong while response proccessing. Details - #{error.class}"
59
-
60
- fetch_errors
61
- end
24
+ def delete?
25
+ method.eql?(:delete)
62
26
  end
63
27
 
64
- def perform_payload(query)
65
- return query if query.is_a?(File)
66
-
67
- get_request? ? { params: fetch_cleared_query(query) } : fetch_cleared_query(query).to_json
28
+ def delete
29
+ connection.delete
68
30
  end
69
31
 
70
- def download_file(url)
71
- download = URI.parse(url).open
72
- destination = @destination || download.meta['content-disposition']
73
- .match(/filename=("?)(.+)\1/)[2]
74
-
75
- IO.copy_stream(download, destination)
76
-
77
- destination
78
- rescue StandardError => error
79
- client.log! error
32
+ def process_with_body
33
+ connection.send(method, prepare_payload(payload[:params]), payload[:headers]) { |response, _, _| response }
34
+ end
80
35
 
81
- @errors << "Something went wrong while downloading file. Details - #{error.class}"
36
+ def post?
37
+ method.eql?(:post)
82
38
  end
39
+ alias post process_with_body
83
40
 
84
- def fetch_errors
85
- @errors.join(';')
41
+ def patch?
42
+ method.eql?(:patch)
86
43
  end
44
+ alias patch process_with_body
87
45
 
88
- def fetch_response_data(doc)
89
- if doc['data'].is_a?(Hash) && doc['data']['url'] && doc['data']['url'].include?('response-content-disposition')
90
- download_file(doc['data']['url'])
91
- else
92
- doc
93
- end
46
+ def put?
47
+ method.eql?(:put)
94
48
  end
49
+ alias put process_with_body
95
50
 
96
- def fetch_cleared_query(query)
97
- case query
98
- when Array
99
- query.map do |el|
100
- el.reject { |_, value| value.nil? }
101
- end.reject(&:empty?)
102
- when Hash
103
- query.reject { |_, value| value.nil? }
104
- else
105
- query
51
+ private
52
+
53
+ def build_payload(payload)
54
+ %i[params headers].each do |key|
55
+ payload[key] ||= {}
56
+ end
57
+ payload
106
58
  end
107
- end
108
59
 
109
- def get_request?
110
- @method.eql?(:get)
111
- end
60
+ def prepare_payload(params)
61
+ return params if params.is_a?(File)
112
62
 
113
- def delete_request?
114
- @method.eql?(:delete)
115
- end
63
+ get? ? { params: fetch_cleared_params(params) } : fetch_cleared_params(params).to_json
64
+ end
65
+
66
+ def fetch_cleared_params(params)
67
+ case params
68
+ when Array
69
+ params.map { |el| el.reject { |_, value| value.nil? } }.reject(&:empty?)
70
+ when Hash
71
+ params.reject { |_, value| value.nil? }
72
+ else
73
+ params
74
+ end
75
+ end
116
76
  end
117
77
  end
118
78
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crowdin
4
+ module Web
5
+ class SendRequest
6
+ attr_reader :request
7
+
8
+ def initialize(request, file_destination = nil)
9
+ @request = request
10
+ @file_destination = file_destination
11
+ @errors = []
12
+ end
13
+
14
+ def perform
15
+ parse_response(process_request)
16
+ end
17
+
18
+ private
19
+
20
+ def process_request
21
+ request.send(request.method)
22
+ rescue StandardError => e
23
+ @errors << "Something went wrong while request processing. Details - #{e.message}"
24
+ end
25
+
26
+ def parse_response(response)
27
+ return @errors.join('; ') if @errors.any?
28
+
29
+ begin
30
+ if response
31
+ if response.body.empty?
32
+ response.code
33
+ else
34
+ parsed_body = JSON.parse(response.body)
35
+ parsed_response = fetch_response_data(parsed_body)
36
+
37
+ @errors.any? ? @errors.join('; ') : parsed_response
38
+ end
39
+ end
40
+ rescue StandardError => e
41
+ @errors << "Something went wrong while response processing. Details - #{e.message}"
42
+ @errors.join('; ')
43
+ end
44
+ end
45
+
46
+ def fetch_response_data(doc)
47
+ if doc['data'].is_a?(Hash) && doc['data']['url'] && doc['data']['url'].include?('response-content-disposition')
48
+ download_file(doc['data']['url'])
49
+ else
50
+ doc
51
+ end
52
+ end
53
+
54
+ def download_file(url)
55
+ download = URI.parse(url).open
56
+ destination = @file_destination || download.meta['content-disposition']
57
+ .match(/filename=("?)(.+)\1/)[2]
58
+
59
+ IO.copy_stream(download, destination)
60
+
61
+ destination
62
+ rescue StandardError => e
63
+ @errors << "Something went wrong while downloading file. Details - #{e.message}"
64
+ end
65
+ end
66
+ end
67
+ end