deepl-rb 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ module DeepL
2
+ class API
3
+ attr_reader :configuration
4
+
5
+ def initialize(configuration)
6
+ @configuration = configuration
7
+ configuration.validate!
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module DeepL
2
+ class Configuration
3
+ ATTRIBUTES = %i[auth_key host].freeze
4
+
5
+ attr_accessor(*ATTRIBUTES)
6
+
7
+ def initialize(data = {})
8
+ data.each { |key, value| send("#{key}=", value) }
9
+ @auth_key ||= ENV['DEEPL_AUTH_KEY']
10
+ @host ||= 'https://api.deepl.com'
11
+ end
12
+
13
+ def validate!
14
+ raise Exceptions::Error, 'auth_key not provided' if auth_key.nil? || auth_key.empty?
15
+ end
16
+
17
+ def attributes
18
+ ATTRIBUTES.map { |attr| [attr, send(attr)] }.to_h
19
+ end
20
+
21
+ def ==(other)
22
+ attributes == other.attributes
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module DeepL
2
+ module Exceptions
3
+ class AuthorizationFailed < RequestError
4
+ def message
5
+ 'Authorization failed. Please supply a valid auth_key parameter.'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module DeepL
2
+ module Exceptions
3
+ class BadRequest < RequestError
4
+ def message
5
+ JSON.parse(response.body)['message']
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module DeepL
2
+ module Exceptions
3
+ class Error < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module DeepL
2
+ module Exceptions
3
+ class LimitExceeded < RequestError
4
+ def message
5
+ 'Limit exceeded. Please wait and send your request once again.'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module DeepL
2
+ module Exceptions
3
+ class RequestError < Error
4
+ attr_reader :request, :response
5
+
6
+ def initialize(request, response)
7
+ @request = request
8
+ @response = response
9
+ end
10
+
11
+ def message
12
+ 'Unkown error.'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,72 @@
1
+ module DeepL
2
+ module Requests
3
+ class Base
4
+ API_VERSION = 'v1'.freeze
5
+
6
+ attr_reader :api, :response
7
+
8
+ def initialize(api)
9
+ @api = api
10
+ end
11
+
12
+ def request
13
+ raise NotImplementedError
14
+ end
15
+
16
+ private
17
+
18
+ def post(payload)
19
+ request = Net::HTTP::Post.new(uri.request_uri)
20
+ request.set_form_data(payload.compact)
21
+ response = http.request(request)
22
+
23
+ validate_response!(request, response)
24
+ [request, response]
25
+ end
26
+
27
+ def http
28
+ @http ||= begin
29
+ http = Net::HTTP.new(uri.host, uri.port)
30
+ http.use_ssl = uri.scheme == 'https'
31
+ http
32
+ end
33
+ end
34
+
35
+ def validate_response!(request, response)
36
+ return if response.is_a?(Net::HTTPSuccess)
37
+
38
+ case response.code
39
+ when '400' then raise Exceptions::BadRequest.new(request, response)
40
+ when '403' then raise Exceptions::AuthorizationFailed.new(request, response)
41
+ when '429' then raise Exceptions::LimitExceeded.new(request, response)
42
+ else raise Exceptions::RequestError.new(request, response)
43
+ end
44
+ end
45
+
46
+ def path
47
+ raise NotImplementedError
48
+ end
49
+
50
+ def url
51
+ "#{host}/#{API_VERSION}/#{path}"
52
+ end
53
+
54
+ def uri
55
+ @uri ||= begin
56
+ uri = URI(url)
57
+ new_query = URI.decode_www_form(uri.query || '') + query_params.to_a
58
+ uri.query = URI.encode_www_form(new_query)
59
+ uri
60
+ end
61
+ end
62
+
63
+ def host
64
+ api.configuration.host
65
+ end
66
+
67
+ def query_params
68
+ { auth_key: api.configuration.auth_key }
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,36 @@
1
+ module DeepL
2
+ module Requests
3
+ class TranslateText < Base
4
+ attr_reader :text, :source_lang, :target_lang
5
+
6
+ def initialize(api, text, source_lang, target_lang)
7
+ super(api)
8
+ @text = text
9
+ @source_lang = source_lang
10
+ @target_lang = target_lang
11
+ end
12
+
13
+ def request
14
+ payload = { text: text, source_lang: source_lang, target_lang: target_lang }
15
+ build_texts(*post(payload))
16
+ end
17
+
18
+ private
19
+
20
+ def build_texts(request, response)
21
+ data = JSON.parse(response.body)
22
+
23
+ texts = data['translations'].map do |translation|
24
+ Resources::Text.new(translation['text'], translation['detected_source_language'],
25
+ request, response)
26
+ end
27
+
28
+ texts.size == 1 ? texts.first : texts
29
+ end
30
+
31
+ def path
32
+ 'translate'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ module DeepL
2
+ module Resources
3
+ class Base
4
+ attr_reader :request, :response
5
+
6
+ def initialize(request, response)
7
+ @request = request
8
+ @response = response
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module DeepL
2
+ module Resources
3
+ class Text < Base
4
+ attr_reader :text, :detected_source_language
5
+
6
+ def initialize(text, detected_source_language, *args)
7
+ super(*args)
8
+
9
+ @text = text
10
+ @detected_source_language = detected_source_language
11
+ end
12
+
13
+ def to_s
14
+ text
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe DeepL::API do
4
+ let(:configuration) { DeepL::Configuration.new }
5
+ subject { DeepL::API.new(configuration) }
6
+
7
+ describe '#initialize' do
8
+ context 'When building an API object' do
9
+ it 'should save the configuration' do
10
+ expect(subject.configuration).to be(configuration)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe DeepL::Configuration do
4
+ let(:attributes) { {} }
5
+ subject { DeepL::Configuration.new(attributes) }
6
+
7
+ describe '#initialize' do
8
+ context 'When using default configuration attributes' do
9
+ it 'should use default attributes' do
10
+ expect(subject.auth_key).to eq(ENV['DEEPL_AUTH_KEY'])
11
+ expect(subject.host).to eq('https://api.deepl.com')
12
+ end
13
+ end
14
+
15
+ context 'When using custom configuration attributes' do
16
+ let(:attributes) { { auth_key: 'SAMPLE', host: 'http://www.example.org' } }
17
+
18
+ it 'should use custom attributes' do
19
+ expect(subject.auth_key).to eq(attributes[:auth_key])
20
+ expect(subject.host).to eq(attributes[:host])
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#validate!' do
26
+ let(:auth_message) { 'auth_key not provided' }
27
+
28
+ context 'When providing a valid auth key' do
29
+ let(:attributes) { { auth_key: '' } }
30
+
31
+ it 'should raise an error' do
32
+ expect { subject.validate! }.to raise_error(DeepL::Exceptions::Error, auth_message)
33
+ end
34
+ end
35
+
36
+ context 'When providing an invalid auth key' do
37
+ let(:attributes) { { auth_key: 'not-empty' } }
38
+
39
+ it 'should not raise an error' do
40
+ expect { subject.validate! }.not_to raise_error
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe DeepL do
4
+ subject { DeepL.dup }
5
+
6
+ describe '#configure' do
7
+ context 'When providing no block' do
8
+ let(:configuration) { DeepL::Configuration.new }
9
+ before { subject.configure }
10
+
11
+ it 'should use default configuration' do
12
+ expect(subject.configuration).to eq(configuration)
13
+ end
14
+ end
15
+
16
+ context 'When providing a valid configuration' do
17
+ let(:configuration) do
18
+ DeepL::Configuration.new(auth_key: 'VALID', host: 'http://www.example.org')
19
+ end
20
+ before do
21
+ subject.configure do |config|
22
+ config.auth_key = configuration.auth_key
23
+ config.host = configuration.host
24
+ end
25
+ end
26
+
27
+ it 'should use the provided configuration' do
28
+ expect(subject.configuration).to eq(configuration)
29
+ end
30
+ end
31
+
32
+ context 'When providing an invalid configuration' do
33
+ it 'should raise an error' do
34
+ expect { subject.configure { |c| c.auth_key = '' } }
35
+ .to raise_error(DeepL::Exceptions::Error)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#translate' do
41
+ let(:input) { 'Sample' }
42
+ let(:source_lang) { 'EN' }
43
+ let(:target_lang) { 'ES' }
44
+
45
+ around do |example|
46
+ VCR.use_cassette('deepl_translate') { example.call }
47
+ end
48
+
49
+ context 'When translating a text' do
50
+ it 'should create and call a request object' do
51
+ expect(DeepL::Requests::TranslateText).to receive(:new)
52
+ .with(subject.api, input, source_lang, target_lang).and_call_original
53
+
54
+ text = subject.translate(input, source_lang: source_lang, target_lang: target_lang)
55
+ expect(text).to be_a(DeepL::Resources::Text)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,110 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.deepl.com/v1/translate?auth_key=VALID_TOKEN
6
+ body:
7
+ encoding: US-ASCII
8
+ string: source_lang=EN&target_lang=ES
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ Content-Type:
17
+ - application/x-www-form-urlencoded
18
+ response:
19
+ status:
20
+ code: 400
21
+ message: Bad Request
22
+ headers:
23
+ Server:
24
+ - nginx
25
+ Date:
26
+ - Sun, 10 Dec 2017 21:20:25 GMT
27
+ Content-Length:
28
+ - '45'
29
+ Connection:
30
+ - keep-alive
31
+ body:
32
+ encoding: UTF-8
33
+ string: '{"message":"Parameter ''text'' not specified."}'
34
+ http_version:
35
+ recorded_at: Sun, 10 Dec 2017 21:20:25 GMT
36
+ - request:
37
+ method: post
38
+ uri: https://api.deepl.com/v1/translate?auth_key=VALID_TOKEN
39
+ body:
40
+ encoding: US-ASCII
41
+ string: text=Abc&source_lang=EN&target_lang=ES
42
+ headers:
43
+ Accept-Encoding:
44
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
45
+ Accept:
46
+ - "*/*"
47
+ User-Agent:
48
+ - Ruby
49
+ Content-Type:
50
+ - application/x-www-form-urlencoded
51
+ response:
52
+ status:
53
+ code: 200
54
+ message: OK
55
+ headers:
56
+ Server:
57
+ - nginx
58
+ Date:
59
+ - Sun, 10 Dec 2017 21:21:23 GMT
60
+ Content-Type:
61
+ - application/json
62
+ Content-Length:
63
+ - '65'
64
+ Connection:
65
+ - keep-alive
66
+ Access-Control-Allow-Origin:
67
+ - "*"
68
+ body:
69
+ encoding: UTF-8
70
+ string: '{"translations":[{"detected_source_language":"EN","text":"ABC"}]}'
71
+ http_version:
72
+ recorded_at: Sun, 10 Dec 2017 21:21:23 GMT
73
+ - request:
74
+ method: post
75
+ uri: https://api.deepl.com/v1/translate?auth_key=VALID_TOKEN
76
+ body:
77
+ encoding: US-ASCII
78
+ string: text=Sample&source_lang=EN&target_lang=ES
79
+ headers:
80
+ Accept-Encoding:
81
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
82
+ Accept:
83
+ - "*/*"
84
+ User-Agent:
85
+ - Ruby
86
+ Content-Type:
87
+ - application/x-www-form-urlencoded
88
+ response:
89
+ status:
90
+ code: 200
91
+ message: OK
92
+ headers:
93
+ Server:
94
+ - nginx
95
+ Date:
96
+ - Sun, 10 Dec 2017 21:22:11 GMT
97
+ Content-Type:
98
+ - application/json
99
+ Content-Length:
100
+ - '69'
101
+ Connection:
102
+ - keep-alive
103
+ Access-Control-Allow-Origin:
104
+ - "*"
105
+ body:
106
+ encoding: UTF-8
107
+ string: '{"translations":[{"detected_source_language":"EN","text":"Muestra"}]}'
108
+ http_version:
109
+ recorded_at: Sun, 10 Dec 2017 21:22:11 GMT
110
+ recorded_with: VCR 4.0.0