crowdin-api 1.1.1 → 1.5.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +31 -0
  3. data/.github/workflows/test-and-lint.yml +1 -1
  4. data/.gitignore +2 -2
  5. data/.rubocop_todo.yml +114 -48
  6. data/Gemfile +3 -0
  7. data/README.md +61 -17
  8. data/bin/crowdin-console +5 -5
  9. data/crowdin-api.gemspec +1 -2
  10. data/lib/crowdin-api/api_resources/bundles.rb +104 -0
  11. data/lib/crowdin-api/api_resources/dictionaries.rb +32 -0
  12. data/lib/crowdin-api/api_resources/distributions.rb +92 -0
  13. data/lib/crowdin-api/api_resources/glossaries.rb +248 -0
  14. data/lib/crowdin-api/api_resources/labels.rb +98 -0
  15. data/lib/crowdin-api/api_resources/languages.rb +61 -0
  16. data/lib/crowdin-api/api_resources/machine_translation_engines.rb +79 -0
  17. data/lib/crowdin-api/api_resources/projects.rb +151 -0
  18. data/lib/crowdin-api/api_resources/reports.rb +184 -0
  19. data/lib/crowdin-api/api_resources/screenshots.rb +172 -0
  20. data/lib/crowdin-api/api_resources/source_files.rb +305 -0
  21. data/lib/crowdin-api/{api-resources → api_resources}/source_strings.rb +19 -24
  22. data/lib/crowdin-api/api_resources/storages.rb +66 -0
  23. data/lib/crowdin-api/api_resources/string_comments.rb +68 -0
  24. data/lib/crowdin-api/api_resources/string_translations.rb +193 -0
  25. data/lib/crowdin-api/api_resources/tasks.rb +102 -0
  26. data/lib/crowdin-api/api_resources/teams.rb +135 -0
  27. data/lib/crowdin-api/api_resources/translation_memory.rb +131 -0
  28. data/lib/crowdin-api/{api-resources → api_resources}/translation_status.rb +24 -30
  29. data/lib/crowdin-api/{api-resources → api_resources}/translations.rb +41 -59
  30. data/lib/crowdin-api/api_resources/users.rb +161 -0
  31. data/lib/crowdin-api/api_resources/vendors.rb +21 -0
  32. data/lib/crowdin-api/api_resources/webhooks.rb +68 -0
  33. data/lib/crowdin-api/api_resources/workflows.rb +59 -0
  34. data/lib/crowdin-api/client/client.rb +155 -47
  35. data/lib/crowdin-api/client/configuration.rb +16 -12
  36. data/lib/crowdin-api/client/version.rb +1 -1
  37. data/lib/crowdin-api/core/errors.rb +3 -1
  38. data/lib/crowdin-api/core/{api_errors_raiser.rb → errors_raisers.rb} +21 -11
  39. data/lib/crowdin-api/core/fetch_all_extensions.rb +9 -0
  40. data/lib/crowdin-api/core/request.rb +50 -90
  41. data/lib/crowdin-api/core/send_request.rb +67 -0
  42. data/lib/crowdin-api.rb +21 -11
  43. data/spec/api_resources/bundles_spec.rb +61 -0
  44. data/spec/api_resources/dictionaries_spec.rb +23 -0
  45. data/spec/api_resources/distributions_spec.rb +71 -0
  46. data/spec/api_resources/glossaries_spec.rb +210 -0
  47. data/spec/api_resources/labels_spec.rb +71 -0
  48. data/spec/api_resources/languages_spec.rb +51 -0
  49. data/spec/api_resources/machine_translation_engines_spec.rb +63 -0
  50. data/spec/api_resources/projects_spec.rb +215 -0
  51. data/spec/api_resources/reports_spec.rb +145 -0
  52. data/spec/api_resources/screenshots_spec.rb +134 -0
  53. data/spec/api_resources/source_files_spec.rb +184 -0
  54. data/spec/api_resources/source_strings_spec.rb +51 -0
  55. data/spec/api_resources/storages_spec.rb +41 -0
  56. data/spec/api_resources/string_comments_spec.rb +51 -0
  57. data/spec/api_resources/string_translations_spec.rb +141 -0
  58. data/spec/api_resources/tasks_spec.rb +79 -0
  59. data/spec/api_resources/teams_spec.rb +100 -0
  60. data/spec/api_resources/translation_memory_spec.rb +114 -0
  61. data/spec/api_resources/translation_status_spec.rb +61 -0
  62. data/spec/api_resources/translations_spec.rb +107 -0
  63. data/spec/api_resources/users_spec.rb +117 -0
  64. data/spec/api_resources/vendors_spec.rb +13 -0
  65. data/spec/api_resources/webhooks_spec.rb +51 -0
  66. data/spec/api_resources/workflows_spec.rb +41 -0
  67. data/spec/spec_helper.rb +23 -2
  68. data/spec/unit/client_spec.rb +91 -0
  69. metadata +69 -28
  70. data/bin/setup +0 -6
  71. data/lib/crowdin-api/api-resources/languages.rb +0 -81
  72. data/lib/crowdin-api/api-resources/projects.rb +0 -134
  73. data/lib/crowdin-api/api-resources/source_files.rb +0 -303
  74. data/lib/crowdin-api/api-resources/storages.rb +0 -102
  75. data/lib/crowdin-api/api-resources/workflows.rb +0 -59
  76. data/spec/core/config-instance_spec.rb +0 -72
  77. data/spec/crowdin-api_spec.rb +0 -7
@@ -1,82 +1,190 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # The Crowdin::Client library is used for interactions with a crowdin.com website.
4
+ # A wrapper and interface to the Crowdin API. Please visit the Crowdin developers site
5
+ # for a full explanation of what each of the Crowdin api methods expect and perform.
5
6
  #
6
- # == Example
7
- #
8
- # require 'crowdin-api'
9
- #
10
- # crowdin = Crowdin::Client.new do |config|
11
- # config.api_token = 'YOUR_API_TOKEN'
12
- # end
13
- #
14
- # crowdin.list_projects
7
+ # https://support.crowdin.com/api/v2/
8
+ # https://support.crowdin.com/enterprise/api/
15
9
  #
16
10
  module Crowdin
11
+ #
12
+ # === Example
13
+ #
14
+ # require 'crowdin-api'
15
+ #
16
+ # crowdin = Crowdin::Client.new do |config|
17
+ # config.api_token = 'YOUR_API_TOKEN'
18
+ # end
19
+ #
20
+ # crowdin.list_projects
21
+ #
17
22
  class Client
18
- # A wrapper and interface to the Crowdin api. Please visit the Crowdin developers
19
- # site for a full explanation of what each of the Crowdin api methods
20
- # expect and perform.
21
- #
22
- # https://support.crowdin.com/api/v2/
23
- #
24
- include ApiResources::Languages
25
- include ApiResources::Projects
26
- include ApiResources::SourceFiles
27
- include ApiResources::Storages
28
- include ApiResources::TranslationStatus
29
- include ApiResources::Translations
30
- include ApiResources::Workflows
31
- include ApiResources::SourceStrings
23
+ # Processing API Resources modules to include them to the Client
24
+ API_RESOURCES_MODULES.each do |module_name|
25
+ Client.send(:include, Object.const_get("Crowdin::ApiResources::#{module_name}"))
26
+ end
32
27
 
33
- include Errors::ApiErrorsRaiser
28
+ # Processing Error Raisers modules to include them to the Client
29
+ ERROR_RAISERS_MODULES.each do |module_name|
30
+ Client.send(:include, Object.const_get("Crowdin::Errors::#{module_name}"))
31
+ end
34
32
 
35
- attr_accessor :logger
33
+ include Web::FetchAllExtensions
36
34
 
35
+ # Config instance that includes configuration options for the Client
37
36
  attr_reader :config
37
+ # Instance with established connection through RestClient to the Crowdin API
38
38
  attr_reader :connection
39
+ # Instance with options and headers for RestClient connection
39
40
  attr_reader :options
41
+ # Logger instance
42
+ attr_reader :logger
40
43
 
41
44
  def initialize(&block)
42
45
  build_configuration(&block)
43
46
 
44
- check_logger
45
- check_rest_client_proxy
47
+ update_logger
48
+ update_rest_client_proxy
46
49
 
47
50
  build_connection
48
51
  end
49
52
 
50
- def log!(message)
51
- !config.logger_enabled? || logger.debug(message)
53
+ def log(message)
54
+ !logger_enabled? || logger.debug(message)
52
55
  end
53
56
 
54
- private
57
+ def logger=(logger)
58
+ raise_logger_are_not_enabled_error unless logger_enabled?
55
59
 
56
- def build_configuration
57
- @config = Crowdin::Configuration.new
58
- yield config if block_given?
60
+ @logger = logger
61
+ update_rest_client_logger
59
62
  end
60
63
 
61
- def build_connection
62
- @connection ||= ::RestClient::Resource.new(config.base_url, build_options)
64
+ def enterprise_mode?
65
+ !!config.organization_domain
63
66
  end
64
67
 
65
- def build_options
66
- @options ||= config.options.merge(headers: config.headers)
68
+ def logger_enabled?
69
+ config.logger_enabled?
67
70
  end
68
71
 
69
- def set_default_logger
70
- require 'logger'
71
- @logger ||= Logger.new($stderr)
72
- end
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 api_resource.to_s.start_with?('list_')
107
+ raise(Errors::FetchAllProcessingError, "#{api_resource} method aren't supported for FetchAll")
108
+ end
73
109
 
74
- def check_rest_client_proxy
75
- ENV['http_proxy'] ? ::RestClient.proxy = ENV['http_proxy'] : false
76
- end
110
+ limit = opts[:limit] || Web::FetchAllExtensions::MAX_ITEMS_COUNT_PER_REQUEST
111
+ offset = opts[:offset] || 0
112
+ request_delay = opts[:request_delay] || 0
77
113
 
78
- def check_logger
79
- config.logger_enabled? ? set_default_logger : config.enable_logger = false
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
154
+
155
+ private
156
+
157
+ def build_configuration
158
+ @config = Crowdin::Configuration.new
159
+ yield config if block_given?
160
+ end
161
+
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
81
189
  end
82
190
  end
@@ -5,13 +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
- alias enterprise_mode? organization_domain
14
-
15
14
  def initialize
16
15
  @target_api_url = '/api/v2'
17
16
  end
@@ -20,25 +19,30 @@ module Crowdin
20
19
  {
21
20
  headers: {},
22
21
  timeout: nil,
23
- json: true
22
+ json: true
24
23
  }
25
24
  end
26
25
 
27
26
  def headers
28
27
  {
29
- 'Accept' => 'application/json',
28
+ 'Accept' => 'application/json',
30
29
  'Authorization' => "Bearer #{api_token}",
31
- 'Content-Type' => 'application/json',
32
- 'User-Agent' => "crowdin-rb/#{Crowdin::Client::VERSION}/#{RUBY_VERSION}/#{RUBY_PLATFORM}"
30
+ 'Content-Type' => 'application/json',
31
+ 'User-Agent' => "crowdin-rb/#{Crowdin::Client::VERSION}/#{RUBY_VERSION}/#{RUBY_PLATFORM}"
33
32
  }
34
33
  end
35
34
 
36
35
  def base_url
37
- if enterprise_mode?
38
- organization_domain.include?('.com') ? organization_domain : "https://#{organization_domain}.api.crowdin.com"
39
- else
40
- 'https://api.crowdin.com'
41
- end
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
42
46
  end
43
47
  end
44
48
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Crowdin
4
4
  class Client
5
- VERSION = '1.1.1'
5
+ VERSION = '1.5.0'
6
6
  end
7
7
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Crowdin
4
4
  module Errors
5
- class OnlyForEnterpriseMode < StandardError; end
5
+ class OnlyForEnterpriseModeError < StandardError; end
6
+ class LoggerAreNotEnabledError < StandardError; end
7
+ class FetchAllProcessingError < StandardError; end
6
8
  end
7
9
  end
@@ -2,9 +2,29 @@
2
2
 
3
3
  module Crowdin
4
4
  module Errors
5
+ # Client errors raiser
6
+ module ClientErrorsRaiser
7
+ def raise_logger_are_not_enabled_error
8
+ raise(LoggerAreNotEnabledError, 'Logger are not enabled in your Client configuration, enable it ' \
9
+ 'before setting your logger')
10
+ end
11
+ end
12
+
13
+ # Command-Line Client errors raiser
14
+ module ClcErrorsRaiser
15
+ def raise_api_token_is_required_error
16
+ raise(ArgumentError, '--api-token option is required')
17
+ end
18
+
19
+ def raise_organization_domain_is_required_error
20
+ raise(ArgumentError, '--organization-domain option is required for Enterprise mode')
21
+ end
22
+ end
23
+
24
+ # API errors raiser
5
25
  module ApiErrorsRaiser
6
26
  def raise_only_for_enterprise_mode_error
7
- raise(OnlyForEnterpriseMode, 'This method can be called only for Enterprise mode')
27
+ raise(OnlyForEnterpriseModeError, 'This method can be called only for Enterprise mode')
8
28
  end
9
29
 
10
30
  def raise_project_id_is_required_error
@@ -14,16 +34,6 @@ module Crowdin
14
34
  def raise_parameter_is_required_error(parameter)
15
35
  raise(ArgumentError, ":#{parameter} is required")
16
36
  end
17
-
18
- # crowdin-console errors
19
-
20
- def raise_api_token_is_required_error
21
- raise(ArgumentError, '--api-token option is required')
22
- end
23
-
24
- def raise_organization_domain_is_required_error
25
- raise(ArgumentError, '--organization-domain option is required for Enterprise mode')
26
- end
27
37
  end
28
38
  end
29
39
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crowdin
4
+ module Web
5
+ module FetchAllExtensions
6
+ MAX_ITEMS_COUNT_PER_REQUEST = 500.freeze
7
+ end
8
+ end
9
+ 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 proccessing request. 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 proccessing response. 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
data/lib/crowdin-api.rb CHANGED
@@ -1,5 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module Crowdin
4
+ # API Resources modules
5
+ API_RESOURCES_MODULES = %i[Storages Languages Projects Workflows SourceFiles Translations SourceStrings
6
+ StringTranslations StringComments Screenshots Glossaries TranslationMemory
7
+ MachineTranslationEngines Reports Tasks Users Teams Vendors Webhooks
8
+ Dictionaries Distributions Labels TranslationStatus Bundles].freeze
9
+
10
+ # Error Raisers modules
11
+ ERROR_RAISERS_MODULES = %i[ApiErrorsRaiser ClientErrorsRaiser].freeze
12
+ end
13
+
3
14
  # Libs
4
15
  require 'json'
5
16
  require 'open-uri'
@@ -7,20 +18,19 @@ require 'rest-client'
7
18
 
8
19
  # Core modules
9
20
  require 'crowdin-api/core/errors'
10
- require 'crowdin-api/core/api_errors_raiser'
21
+ require 'crowdin-api/core/errors_raisers'
11
22
  require 'crowdin-api/core/request'
23
+ require 'crowdin-api/core/send_request'
24
+ require 'crowdin-api/core/fetch_all_extensions'
12
25
 
13
- # Api modules
14
- require 'crowdin-api/api-resources/languages'
15
- require 'crowdin-api/api-resources/projects'
16
- require 'crowdin-api/api-resources/source_files'
17
- require 'crowdin-api/api-resources/storages'
18
- require 'crowdin-api/api-resources/translation_status'
19
- require 'crowdin-api/api-resources/translations'
20
- require 'crowdin-api/api-resources/workflows'
21
- require 'crowdin-api/api-resources/source_strings'
26
+ # API modules
27
+ Crowdin::API_RESOURCES_MODULES.each do |api_resource|
28
+ require "crowdin-api/api_resources/#{api_resource.to_s.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase}"
29
+ rescue LoadError
30
+ # Ignored
31
+ end
22
32
 
23
- # Client
33
+ # Client modules
24
34
  require 'crowdin-api/client/version'
25
35
  require 'crowdin-api/client/configuration'
26
36
  require 'crowdin-api/client/client'