evolution_api 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +483 -0
- data/bin/test_gem.rb +162 -0
- data/lib/evolution_api/chat.rb +82 -0
- data/lib/evolution_api/client.rb +351 -0
- data/lib/evolution_api/contact.rb +74 -0
- data/lib/evolution_api/errors.rb +95 -0
- data/lib/evolution_api/instance.rb +161 -0
- data/lib/evolution_api/message.rb +249 -0
- data/lib/evolution_api/version.rb +5 -0
- data/lib/evolution_api/webhook.rb +44 -0
- data/lib/evolution_api.rb +86 -0
- metadata +226 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EvolutionApi
|
4
|
+
# Classe base para todos os erros da Evolution API
|
5
|
+
class Error < StandardError
|
6
|
+
attr_reader :response, :status_code, :error_code
|
7
|
+
|
8
|
+
def initialize(message = nil, response = nil, status_code = nil, error_code = nil)
|
9
|
+
super(message)
|
10
|
+
@response = response
|
11
|
+
@status_code = status_code
|
12
|
+
@error_code = error_code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Erro de autenticação
|
17
|
+
class AuthenticationError < Error
|
18
|
+
def initialize(message = 'Erro de autenticação', response = nil)
|
19
|
+
super(message, response, 401)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Erro de autorização
|
24
|
+
class AuthorizationError < Error
|
25
|
+
def initialize(message = 'Acesso negado', response = nil)
|
26
|
+
super(message, response, 403)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Erro de recurso não encontrado
|
31
|
+
class NotFoundError < Error
|
32
|
+
def initialize(message = 'Recurso não encontrado', response = nil)
|
33
|
+
super(message, response, 404)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Erro de validação
|
38
|
+
class ValidationError < Error
|
39
|
+
attr_reader :errors
|
40
|
+
|
41
|
+
def initialize(message = 'Erro de validação', response = nil, errors = {})
|
42
|
+
super(message, response, 422)
|
43
|
+
@errors = errors
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Erro de rate limit
|
48
|
+
class RateLimitError < Error
|
49
|
+
def initialize(message = 'Limite de requisições excedido', response = nil)
|
50
|
+
super(message, response, 429)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Erro de servidor
|
55
|
+
class ServerError < Error
|
56
|
+
def initialize(message = 'Erro interno do servidor', response = nil)
|
57
|
+
super(message, response, 500)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Erro de timeout
|
62
|
+
class TimeoutError < Error
|
63
|
+
def initialize(message = 'Timeout na requisição', response = nil)
|
64
|
+
super(message, response, nil)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Erro de conexão
|
69
|
+
class ConnectionError < Error
|
70
|
+
def initialize(message = 'Erro de conexão', response = nil)
|
71
|
+
super(message, response, nil)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Erro de instância não conectada
|
76
|
+
class InstanceNotConnectedError < Error
|
77
|
+
def initialize(instance_name)
|
78
|
+
super("Instância '#{instance_name}' não está conectada", nil, nil, 'INSTANCE_NOT_CONNECTED')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Erro de QR Code expirado
|
83
|
+
class QRCodeExpiredError < Error
|
84
|
+
def initialize
|
85
|
+
super('QR Code expirado', nil, nil, 'QR_CODE_EXPIRED')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Erro de número inválido
|
90
|
+
class InvalidNumberError < Error
|
91
|
+
def initialize(number)
|
92
|
+
super("Número '#{number}' é inválido", nil, nil, 'INVALID_NUMBER')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EvolutionApi
|
4
|
+
# Classe para gerenciar instâncias do WhatsApp
|
5
|
+
class Instance
|
6
|
+
attr_reader :name, :client
|
7
|
+
|
8
|
+
def initialize(name, client)
|
9
|
+
@name = name
|
10
|
+
@client = client
|
11
|
+
end
|
12
|
+
|
13
|
+
# Obtém informações da instância
|
14
|
+
def info
|
15
|
+
client.get_instance(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Conecta a instância
|
19
|
+
def connect
|
20
|
+
client.connect_instance(name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Desconecta a instância
|
24
|
+
def disconnect
|
25
|
+
client.disconnect_instance(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Remove a instância
|
29
|
+
def delete
|
30
|
+
client.delete_instance(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Obtém QR Code para conexão
|
34
|
+
def qr_code
|
35
|
+
client.get_qr_code(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Verifica se a instância está conectada
|
39
|
+
def connected?
|
40
|
+
info = self.info
|
41
|
+
info['status'] == 'open'
|
42
|
+
rescue StandardError
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
# Envia uma mensagem de texto
|
47
|
+
def send_text(number, text, options = {})
|
48
|
+
client.send_text_message(name, number, text, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Envia uma mensagem de imagem
|
52
|
+
def send_image(number, image_url, caption = nil, options = {})
|
53
|
+
client.send_image_message(name, number, image_url, caption, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Envia uma mensagem de áudio
|
57
|
+
def send_audio(number, audio_url, options = {})
|
58
|
+
client.send_audio_message(name, number, audio_url, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Envia uma mensagem de vídeo
|
62
|
+
def send_video(number, video_url, caption = nil, options = {})
|
63
|
+
client.send_video_message(name, number, video_url, caption, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Envia um documento
|
67
|
+
def send_document(number, document_url, caption = nil, options = {})
|
68
|
+
client.send_document_message(name, number, document_url, caption, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Envia uma localização
|
72
|
+
def send_location(number, latitude, longitude, description = nil)
|
73
|
+
client.send_location_message(name, number, latitude, longitude, description)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Envia um contato
|
77
|
+
def send_contact(number, contact_number, contact_name)
|
78
|
+
client.send_contact_message(name, number, contact_number, contact_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Envia uma mensagem com botões
|
82
|
+
def send_button(number, title, description, buttons)
|
83
|
+
client.send_button_message(name, number, title, description, buttons)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Envia uma lista de opções
|
87
|
+
def send_list(number, title, description, sections)
|
88
|
+
client.send_list_message(name, number, title, description, sections)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Obtém chats da instância
|
92
|
+
def chats
|
93
|
+
client.get_chats(name)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Obtém mensagens de um chat
|
97
|
+
def messages(number, options = {})
|
98
|
+
client.get_messages(name, number, options)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Marca mensagens como lidas
|
102
|
+
def mark_as_read(number)
|
103
|
+
client.mark_messages_as_read(name, number)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Arquivar chat
|
107
|
+
def archive_chat(number)
|
108
|
+
client.archive_chat(name, number)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Desarquivar chat
|
112
|
+
def unarchive_chat(number)
|
113
|
+
client.unarchive_chat(name, number)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Deletar chat
|
117
|
+
def delete_chat(number)
|
118
|
+
client.delete_chat(name, number)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Obtém contatos da instância
|
122
|
+
def contacts
|
123
|
+
client.get_contacts(name)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Obtém informações de um contato
|
127
|
+
def contact(number)
|
128
|
+
client.get_contact(name, number)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Verifica se um número existe no WhatsApp
|
132
|
+
def check_number(number)
|
133
|
+
client.check_number(name, number)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Bloqueia um contato
|
137
|
+
def block_contact(number)
|
138
|
+
client.block_contact(name, number)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Desbloqueia um contato
|
142
|
+
def unblock_contact(number)
|
143
|
+
client.unblock_contact(name, number)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Configura webhook
|
147
|
+
def set_webhook(webhook_url, events = nil)
|
148
|
+
client.set_webhook(name, webhook_url, events)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Obtém configuração de webhook
|
152
|
+
def webhook
|
153
|
+
client.get_webhook(name)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Remove webhook
|
157
|
+
def delete_webhook
|
158
|
+
client.delete_webhook(name)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EvolutionApi
|
4
|
+
# Classe para representar mensagens do WhatsApp
|
5
|
+
class Message
|
6
|
+
attr_reader :id, :key, :message, :message_timestamp, :status, :participant, :instance_name
|
7
|
+
|
8
|
+
def initialize(data, instance_name = nil)
|
9
|
+
@id = data['id']
|
10
|
+
@key = data['key']
|
11
|
+
@message = data['message']
|
12
|
+
@message_timestamp = data['messageTimestamp']
|
13
|
+
@status = data['status']
|
14
|
+
@participant = data['participant']
|
15
|
+
@instance_name = instance_name
|
16
|
+
end
|
17
|
+
|
18
|
+
# Verifica se é uma mensagem de texto
|
19
|
+
def text?
|
20
|
+
message&.key?('conversation') || message&.key?('extendedTextMessage')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Obtém o texto da mensagem
|
24
|
+
def text
|
25
|
+
return message['conversation'] if message&.key?('conversation')
|
26
|
+
return message['extendedTextMessage']['text'] if message&.key?('extendedTextMessage')
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Verifica se é uma mensagem de imagem
|
32
|
+
def image?
|
33
|
+
message&.key?('imageMessage')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Obtém informações da imagem
|
37
|
+
def image
|
38
|
+
return nil unless image?
|
39
|
+
|
40
|
+
message['imageMessage']
|
41
|
+
end
|
42
|
+
|
43
|
+
# Verifica se é uma mensagem de áudio
|
44
|
+
def audio?
|
45
|
+
message&.key?('audioMessage')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Obtém informações do áudio
|
49
|
+
def audio
|
50
|
+
return nil unless audio?
|
51
|
+
|
52
|
+
message['audioMessage']
|
53
|
+
end
|
54
|
+
|
55
|
+
# Verifica se é uma mensagem de vídeo
|
56
|
+
def video?
|
57
|
+
message&.key?('videoMessage')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Obtém informações do vídeo
|
61
|
+
def video
|
62
|
+
return nil unless video?
|
63
|
+
|
64
|
+
message['videoMessage']
|
65
|
+
end
|
66
|
+
|
67
|
+
# Verifica se é um documento
|
68
|
+
def document?
|
69
|
+
message&.key?('documentMessage')
|
70
|
+
end
|
71
|
+
|
72
|
+
# Obtém informações do documento
|
73
|
+
def document
|
74
|
+
return nil unless document?
|
75
|
+
|
76
|
+
message['documentMessage']
|
77
|
+
end
|
78
|
+
|
79
|
+
# Verifica se é uma localização
|
80
|
+
def location?
|
81
|
+
message&.key?('locationMessage')
|
82
|
+
end
|
83
|
+
|
84
|
+
# Obtém informações da localização
|
85
|
+
def location
|
86
|
+
return nil unless location?
|
87
|
+
|
88
|
+
message['locationMessage']
|
89
|
+
end
|
90
|
+
|
91
|
+
# Verifica se é um contato
|
92
|
+
def contact?
|
93
|
+
message&.key?('contactMessage')
|
94
|
+
end
|
95
|
+
|
96
|
+
# Obtém informações do contato
|
97
|
+
def contact
|
98
|
+
return nil unless contact?
|
99
|
+
|
100
|
+
message['contactMessage']
|
101
|
+
end
|
102
|
+
|
103
|
+
# Verifica se é uma mensagem de botão
|
104
|
+
def button?
|
105
|
+
message&.key?('buttonsResponseMessage') || message&.key?('buttonMessage')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Obtém informações do botão
|
109
|
+
def button
|
110
|
+
return message['buttonsResponseMessage'] if message&.key?('buttonsResponseMessage')
|
111
|
+
return message['buttonMessage'] if message&.key?('buttonMessage')
|
112
|
+
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
|
116
|
+
# Verifica se é uma lista
|
117
|
+
def list?
|
118
|
+
message&.key?('listResponseMessage') || message&.key?('listMessage')
|
119
|
+
end
|
120
|
+
|
121
|
+
# Obtém informações da lista
|
122
|
+
def list
|
123
|
+
return message['listResponseMessage'] if message&.key?('listResponseMessage')
|
124
|
+
return message['listMessage'] if message&.key?('listMessage')
|
125
|
+
|
126
|
+
nil
|
127
|
+
end
|
128
|
+
|
129
|
+
# Verifica se é uma mensagem de reação
|
130
|
+
def reaction?
|
131
|
+
message&.key?('reactionMessage')
|
132
|
+
end
|
133
|
+
|
134
|
+
# Obtém informações da reação
|
135
|
+
def reaction
|
136
|
+
return nil unless reaction?
|
137
|
+
|
138
|
+
message['reactionMessage']
|
139
|
+
end
|
140
|
+
|
141
|
+
# Verifica se é uma mensagem de sticker
|
142
|
+
def sticker?
|
143
|
+
message&.key?('stickerMessage')
|
144
|
+
end
|
145
|
+
|
146
|
+
# Obtém informações do sticker
|
147
|
+
def sticker
|
148
|
+
return nil unless sticker?
|
149
|
+
|
150
|
+
message['stickerMessage']
|
151
|
+
end
|
152
|
+
|
153
|
+
# Obtém o número do remetente
|
154
|
+
def from
|
155
|
+
key['remoteJid']&.split('@')&.first
|
156
|
+
end
|
157
|
+
|
158
|
+
# Obtém o ID da mensagem
|
159
|
+
def message_id
|
160
|
+
key['id']
|
161
|
+
end
|
162
|
+
|
163
|
+
# Verifica se é uma mensagem de grupo
|
164
|
+
def group?
|
165
|
+
key['remoteJid']&.include?('@g.us')
|
166
|
+
end
|
167
|
+
|
168
|
+
# Verifica se é uma mensagem de broadcast
|
169
|
+
def broadcast?
|
170
|
+
key['remoteJid']&.include?('@broadcast')
|
171
|
+
end
|
172
|
+
|
173
|
+
# Verifica se é uma mensagem privada
|
174
|
+
def private?
|
175
|
+
!group? && !broadcast?
|
176
|
+
end
|
177
|
+
|
178
|
+
# Verifica se a mensagem foi enviada pelo próprio usuário
|
179
|
+
def from_me?
|
180
|
+
key['fromMe'] == true
|
181
|
+
end
|
182
|
+
|
183
|
+
# Obtém o timestamp da mensagem
|
184
|
+
def timestamp
|
185
|
+
Time.at(message_timestamp) if message_timestamp
|
186
|
+
end
|
187
|
+
|
188
|
+
# Verifica se a mensagem foi lida
|
189
|
+
def read?
|
190
|
+
status == 'read'
|
191
|
+
end
|
192
|
+
|
193
|
+
# Verifica se a mensagem foi entregue
|
194
|
+
def delivered?
|
195
|
+
status == 'delivered'
|
196
|
+
end
|
197
|
+
|
198
|
+
# Verifica se a mensagem foi enviada
|
199
|
+
def sent?
|
200
|
+
status == 'sent'
|
201
|
+
end
|
202
|
+
|
203
|
+
# Verifica se a mensagem falhou
|
204
|
+
def failed?
|
205
|
+
status == 'failed'
|
206
|
+
end
|
207
|
+
|
208
|
+
# Obtém o tipo da mensagem
|
209
|
+
def type
|
210
|
+
return 'text' if text?
|
211
|
+
return 'image' if image?
|
212
|
+
return 'audio' if audio?
|
213
|
+
return 'video' if video?
|
214
|
+
return 'document' if document?
|
215
|
+
return 'location' if location?
|
216
|
+
return 'contact' if contact?
|
217
|
+
return 'button' if button?
|
218
|
+
return 'list' if list?
|
219
|
+
return 'reaction' if reaction?
|
220
|
+
return 'sticker' if sticker?
|
221
|
+
|
222
|
+
'unknown'
|
223
|
+
end
|
224
|
+
|
225
|
+
# Converte para hash
|
226
|
+
def to_h
|
227
|
+
{
|
228
|
+
id: id,
|
229
|
+
key: key,
|
230
|
+
message: message,
|
231
|
+
message_timestamp: message_timestamp,
|
232
|
+
status: status,
|
233
|
+
participant: participant,
|
234
|
+
instance_name: instance_name,
|
235
|
+
type: type,
|
236
|
+
from: from,
|
237
|
+
from_me: from_me?,
|
238
|
+
group: group?,
|
239
|
+
timestamp: timestamp,
|
240
|
+
text: text
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
# Converte para JSON
|
245
|
+
def to_json(*args)
|
246
|
+
to_h.to_json(*args)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EvolutionApi
|
4
|
+
# Classe para gerenciar webhooks da Evolution API
|
5
|
+
class Webhook
|
6
|
+
attr_reader :url, :events, :instance_name
|
7
|
+
|
8
|
+
def initialize(data, instance_name = nil)
|
9
|
+
@url = data['webhook']
|
10
|
+
@events = data['events'] || []
|
11
|
+
@instance_name = instance_name
|
12
|
+
end
|
13
|
+
|
14
|
+
# Verifica se o webhook está configurado
|
15
|
+
def configured?
|
16
|
+
!url.nil? && !url.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
# Verifica se um evento específico está habilitado
|
20
|
+
def event_enabled?(event)
|
21
|
+
events.include?(event)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Lista todos os eventos habilitados
|
25
|
+
def enabled_events
|
26
|
+
events.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
# Converte para hash
|
30
|
+
def to_h
|
31
|
+
{
|
32
|
+
url: url,
|
33
|
+
events: events,
|
34
|
+
configured: configured?,
|
35
|
+
instance_name: instance_name
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Converte para JSON
|
40
|
+
def to_json(*args)
|
41
|
+
to_h.to_json(*args)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'json'
|
5
|
+
require 'dry/configurable'
|
6
|
+
require 'dry/validation'
|
7
|
+
|
8
|
+
require_relative 'evolution_api/version'
|
9
|
+
require_relative 'evolution_api/client'
|
10
|
+
require_relative 'evolution_api/instance'
|
11
|
+
require_relative 'evolution_api/message'
|
12
|
+
require_relative 'evolution_api/chat'
|
13
|
+
require_relative 'evolution_api/contact'
|
14
|
+
require_relative 'evolution_api/webhook'
|
15
|
+
require_relative 'evolution_api/errors'
|
16
|
+
|
17
|
+
# Evolution API Ruby Client
|
18
|
+
#
|
19
|
+
# Uma gem Ruby para consumir facilmente a Evolution API,
|
20
|
+
# permitindo integração com WhatsApp através de uma API REST simples e poderosa.
|
21
|
+
#
|
22
|
+
# @example Configuração básica
|
23
|
+
# EvolutionApi.configure do |config|
|
24
|
+
# config.base_url = "http://localhost:8080"
|
25
|
+
# config.api_key = "sua_api_key_aqui"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Uso básico
|
29
|
+
# client = EvolutionApi::Client.new
|
30
|
+
# instances = client.list_instances
|
31
|
+
# client.send_message("instance_name", "5511999999999", "Olá!")
|
32
|
+
#
|
33
|
+
# @see https://doc.evolution-api.com/ Evolution API Documentation
|
34
|
+
module EvolutionApi
|
35
|
+
extend Dry::Configurable
|
36
|
+
|
37
|
+
# Configurações padrão
|
38
|
+
setting :base_url, default: 'http://localhost:8080'
|
39
|
+
setting :api_key, default: nil
|
40
|
+
setting :timeout, default: 30
|
41
|
+
setting :retry_attempts, default: 3
|
42
|
+
setting :retry_delay, default: 1
|
43
|
+
|
44
|
+
# Configuração de webhooks
|
45
|
+
setting :webhook_url, default: nil
|
46
|
+
setting :webhook_events, default: %w[connection.update message.upsert]
|
47
|
+
|
48
|
+
# Configuração de logs
|
49
|
+
setting :logger, default: nil
|
50
|
+
setting :log_level, default: :info
|
51
|
+
|
52
|
+
# Configuração de cache
|
53
|
+
setting :cache_enabled, default: false
|
54
|
+
setting :cache_ttl, default: 300 # 5 minutos
|
55
|
+
|
56
|
+
class << self
|
57
|
+
# Configura a gem com as opções fornecidas
|
58
|
+
#
|
59
|
+
# @param options [Hash] Opções de configuração
|
60
|
+
# @yield [config] Bloco para configuração
|
61
|
+
# @yieldparam config [Dry::Configurable::Config] Objeto de configuração
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# EvolutionApi.configure do |config|
|
65
|
+
# config.base_url = "https://api.evolution.com"
|
66
|
+
# config.api_key = "sua_chave_api"
|
67
|
+
# config.timeout = 60
|
68
|
+
# end
|
69
|
+
def configure(options = {})
|
70
|
+
options.each { |key, value| config.public_send("#{key}=", value) }
|
71
|
+
yield config if block_given?
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retorna um novo cliente configurado
|
75
|
+
#
|
76
|
+
# @return [EvolutionApi::Client] Cliente configurado
|
77
|
+
def client
|
78
|
+
@client ||= Client.new
|
79
|
+
end
|
80
|
+
|
81
|
+
# Reseta o cliente (útil para testes)
|
82
|
+
def reset_client!
|
83
|
+
@client = nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|