chatgpt_assistant 0.1.2 → 0.1.4
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 +4 -4
- data/.env_prod_sample +1 -1
- data/.env_sample +1 -1
- data/.rubocop.yml +17 -5
- data/Dockerfile +2 -5
- data/Gemfile +1 -1
- data/Gemfile.lock +6 -6
- data/SECURITY.md +15 -0
- data/exe/chatgpt_assistant +2 -2
- data/exe/chatgpt_bot +1 -1
- data/lib/bots/application_bot.rb +22 -91
- data/lib/bots/discord_bot.rb +102 -241
- data/lib/bots/helpers/audio_helper.rb +18 -0
- data/lib/bots/helpers/authentication_helper.rb +47 -0
- data/lib/bots/helpers/discord_helper.rb +102 -0
- data/lib/bots/helpers/discord_voice_helper.rb +50 -0
- data/lib/bots/helpers/file_helper.rb +10 -0
- data/lib/bots/helpers/logger_action_helper.rb +14 -0
- data/lib/bots/helpers/messenger_helper.rb +134 -0
- data/lib/bots/helpers/search_helper.rb +34 -0
- data/lib/bots/helpers/telegram_helper.rb +89 -0
- data/lib/bots/helpers/validation_helper.rb +29 -0
- data/lib/bots/helpers/visit_helper.rb +24 -0
- data/lib/bots/telegram_bot.rb +120 -235
- data/lib/chatgpt_assistant/audio_recognition.rb +31 -32
- data/lib/chatgpt_assistant/audio_synthesis.rb +72 -76
- data/lib/chatgpt_assistant/chatter.rb +34 -27
- data/lib/chatgpt_assistant/config.rb +22 -18
- data/lib/chatgpt_assistant/default_messages.rb +108 -108
- data/lib/chatgpt_assistant/migrations.rb +62 -4
- data/lib/chatgpt_assistant/models.rb +53 -7
- data/lib/chatgpt_assistant/version.rb +1 -1
- data/lib/chatgpt_assistant.rb +25 -13
- data/workflows/deploy.yml +19 -0
- data/workflows/deploy_and_build.yml +19 -0
- metadata +22 -6
data/lib/bots/telegram_bot.rb
CHANGED
@@ -1,277 +1,162 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "helpers/telegram_helper"
|
4
|
+
|
3
5
|
module ChatgptAssistant
|
4
6
|
# This class is responsible for the telegram bot features
|
5
7
|
class TelegramBot < ApplicationBot
|
6
8
|
def start
|
7
9
|
bot.listen do |message|
|
10
|
+
next if message.chat.type != "private" # disable group and channel messages, we will enable it later
|
11
|
+
|
8
12
|
@msg = message
|
9
|
-
|
13
|
+
@visitor = telegram_visited?(@msg.chat.id)
|
14
|
+
next unless telegram_text_or_audio?
|
15
|
+
|
16
|
+
text_events if telegram_message_has_text?
|
17
|
+
audio_event if telegram_message_has_audio?
|
10
18
|
end
|
11
|
-
rescue StandardError
|
19
|
+
rescue StandardError => e
|
20
|
+
Error.create(message: e.message, backtrace: e.backtrace)
|
12
21
|
retry
|
13
22
|
end
|
14
23
|
|
15
24
|
private
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
26
|
+
include TelegramHelper
|
27
|
+
|
28
|
+
attr_accessor :msg, :visitor, :chat, :chat_id
|
29
|
+
|
30
|
+
def text_events
|
31
|
+
case msg.text
|
32
|
+
when "/start"
|
33
|
+
start_event
|
34
|
+
when "/help"
|
35
|
+
help_event
|
36
|
+
when "/hist"
|
37
|
+
hist_event
|
38
|
+
when "/list"
|
39
|
+
list_event
|
40
|
+
when "/stop"
|
41
|
+
stop_event
|
42
|
+
when nil
|
43
|
+
nil_event
|
44
|
+
else
|
45
|
+
action_events
|
46
|
+
end
|
47
|
+
end
|
21
48
|
|
22
|
-
|
23
|
-
|
24
|
-
|
49
|
+
def start_event
|
50
|
+
register_visitor_action("start", visitor.id) unless visitor.tel_user
|
51
|
+
register_user_action("start", visitor.tel_user.id) if visitor.tel_user
|
52
|
+
telegram_send_start_message
|
53
|
+
end
|
25
54
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
when "/help"
|
31
|
-
help_event
|
32
|
-
when "/list"
|
33
|
-
list_event
|
34
|
-
when "/stop"
|
35
|
-
stop_event
|
36
|
-
when "/hist"
|
37
|
-
hist_event
|
38
|
-
when nil
|
39
|
-
nil_event
|
40
|
-
else
|
41
|
-
action_events
|
55
|
+
def help_event
|
56
|
+
register_visitor_action("help", visitor.id) unless visitor.tel_user
|
57
|
+
register_user_action("help", visitor.tel_user.id) if visitor.tel_user
|
58
|
+
help_messages.each { |m| send_message m, msg.chat.id }
|
42
59
|
end
|
43
|
-
end
|
44
60
|
|
45
|
-
|
46
|
-
|
61
|
+
def hist_event
|
62
|
+
return not_logged_in_message unless user
|
63
|
+
return no_chat_selected_message unless user.current_chat
|
64
|
+
return no_messages_founded_message if user.current_chat.messages.count.zero?
|
47
65
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
ai_text = chatter.chat(user_audio["text"], chat.id)
|
53
|
-
ai_voice = audio_synthesis.synthesize_text(ai_text)
|
54
|
-
send_audio_message(ai_voice, ai_text)
|
55
|
-
delete_all_voice_files
|
56
|
-
else
|
57
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:message_creation_error])
|
66
|
+
register_user_action("hist", user.id)
|
67
|
+
telegram_user_history.each do |m|
|
68
|
+
send_message m, msg.chat.id
|
69
|
+
end
|
58
70
|
end
|
59
|
-
end
|
60
71
|
|
61
|
-
|
62
|
-
|
63
|
-
bot.api.send_message(chat_id: msg.chat.id, text: text)
|
64
|
-
end
|
72
|
+
def list_event
|
73
|
+
return unless valid_for_list_action?
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
75
|
+
register_user_action("list", user.id)
|
76
|
+
send_message commom_messages[:chat_list], msg.chat.id
|
77
|
+
chats_str = ""
|
78
|
+
user.chats.each_with_index { |c, i| chats_str += "Chat #{i + 1} - #{c.title}\n" }
|
79
|
+
send_message chats_str, msg.chat.id
|
80
|
+
end
|
72
81
|
|
73
|
-
|
74
|
-
|
82
|
+
def action_events
|
83
|
+
return login_event if msg.text.include?("login/")
|
84
|
+
return register_event if msg.text.include?("register/")
|
85
|
+
return new_chat_event if msg.text.include?("new_chat/")
|
86
|
+
return select_chat_event if msg.text.include?("sl_chat/")
|
87
|
+
return telegram_chat_event unless telegram_actions?
|
75
88
|
|
76
|
-
|
77
|
-
user_info = msg.text.split("/").last
|
78
|
-
email, password = user_info.split(":")
|
79
|
-
case auth_usertelegram(email, password, msg.chat.id)
|
80
|
-
when "user not found"
|
81
|
-
user_not_found_error_message
|
82
|
-
when "wrong password"
|
83
|
-
wrong_password_error_message
|
84
|
-
when find_useremail(email)
|
85
|
-
user_logged_in_message
|
89
|
+
invalid_command_error_message
|
86
90
|
end
|
87
|
-
end
|
88
91
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
92
|
+
def login_event
|
93
|
+
register_visitor_action("login", visitor.id) unless visitor.tel_user
|
94
|
+
user_info = msg.text.split("/").last
|
95
|
+
email, password = user_info.split(":")
|
96
|
+
case telegram_user_auth(email, password, msg.chat.id)
|
97
|
+
when "user not found"
|
98
|
+
user_not_found_error_message
|
99
|
+
when "wrong password"
|
100
|
+
wrong_password_error_message
|
101
|
+
when email
|
102
|
+
user_logged_in_message
|
103
|
+
end
|
96
104
|
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def audio
|
100
|
-
msg.audio || msg.voice
|
101
|
-
end
|
102
|
-
|
103
|
-
def audio_info
|
104
|
-
bot.api.get_file(file_id: audio.file_id)
|
105
|
-
end
|
106
|
-
|
107
|
-
def audio_url
|
108
|
-
"https://api.telegram.org/file/bot#{telegram_token}/#{audio_info["result"]["file_path"]}"
|
109
|
-
end
|
110
105
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
help_message = help_messages.join("\n").to_s
|
118
|
-
bot.api.send_message(chat_id: msg.chat.id, text: help_message)
|
119
|
-
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:start_helper])
|
120
|
-
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:start_sec_helper])
|
121
|
-
end
|
122
|
-
|
123
|
-
def hist_event
|
124
|
-
return not_logged_in_message unless user
|
125
|
-
return bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:no_chat_selected]) unless user.current_chat
|
126
|
-
|
127
|
-
if user.current_chat.messages.count.zero?
|
128
|
-
return bot.api.send_message(chat_id: msg.chat.id,
|
129
|
-
text: error_messages[:no_messages_founded])
|
106
|
+
def register_event
|
107
|
+
register_visitor_action("register", visitor.id)
|
108
|
+
user_info = msg.text.split("/").last
|
109
|
+
email, password = user_info.split(":")
|
110
|
+
registered_email = telegram_user_create visitor.id, email, password
|
111
|
+
registered_email == email ? user_created_message : user_creation_error_message
|
130
112
|
end
|
131
113
|
|
132
|
-
|
133
|
-
|
134
|
-
end.join
|
135
|
-
bot.api.send_message(chat_id: msg.chat.id, text: response)
|
136
|
-
end
|
137
|
-
|
138
|
-
def select_chat
|
139
|
-
return not_logged_in_message unless user
|
140
|
-
|
141
|
-
title = msg.text.split("/").last
|
142
|
-
chat = user.chat_by_title(title)
|
143
|
-
return chat_not_found_message unless chat
|
144
|
-
|
145
|
-
user.update(current_chat_id: chat.id)
|
146
|
-
bot.api.send_message(chat_id: msg.chat.id, text: success_messages[:chat_selected])
|
147
|
-
end
|
114
|
+
def new_chat_event
|
115
|
+
return not_logged_in_message unless user
|
148
116
|
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
def create_chat
|
154
|
-
text = msg.text
|
155
|
-
title = text.split("/").last
|
156
|
-
chat = Chat.new(user_id: user.id, status: 0, title: title)
|
157
|
-
chat.save ? chat_created_message(chat) : chat_creation_failed_message
|
158
|
-
end
|
159
|
-
|
160
|
-
def list_event
|
161
|
-
return unless valid_for_list_action?
|
162
|
-
|
163
|
-
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:chat_list])
|
164
|
-
chats_str = ""
|
165
|
-
user.chats.each do |chat|
|
166
|
-
chats_str += "Chat #{chat.id} - #{chat.title}\n"
|
117
|
+
register_user_action("new_chat", user.id)
|
118
|
+
telegram_create_chat
|
167
119
|
end
|
168
|
-
bot.api.send_message(chat_id: msg.chat.id, text: chats_str)
|
169
|
-
end
|
170
|
-
|
171
|
-
def valid_for_list_action?
|
172
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:not_logged_in]) if user.nil?
|
173
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:no_chats_founded]) if user.chats.count.zero?
|
174
|
-
!user.nil? && user.chats.count.positive?
|
175
|
-
end
|
176
|
-
|
177
|
-
def chatter_call
|
178
|
-
user ? chat_if_exists : not_logged_in_message
|
179
|
-
end
|
180
120
|
|
181
|
-
|
182
|
-
|
183
|
-
chat ? chat_success(chat.id) : no_chat_selected
|
184
|
-
end
|
121
|
+
def select_chat_event
|
122
|
+
return not_logged_in_message unless user
|
185
123
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
124
|
+
register_user_action("select_chat", user.id)
|
125
|
+
title = msg.text.split("/").last
|
126
|
+
chat = user.chat_by_title(title)
|
127
|
+
return chat_not_found_message unless chat
|
190
128
|
|
191
|
-
|
192
|
-
|
193
|
-
bot.api.send_message(chat_id: msg.chat.id, text: message)
|
129
|
+
user.update(current_chat_id: chat.id)
|
130
|
+
send_message success_messages[:chat_selected], msg.chat.id
|
194
131
|
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def stop_event
|
198
|
-
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:stop])
|
199
|
-
bot.api.leave_chat(chat_id: msg.chat.id)
|
200
|
-
end
|
201
|
-
|
202
|
-
def nil_event
|
203
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:nil])
|
204
|
-
end
|
205
|
-
|
206
|
-
def user_logged_message
|
207
|
-
user.update(telegram_id: msg.chat.id)
|
208
|
-
bot.api.send_message(chat_id: msg.chat.id, text: success_messages[:user_logged_in])
|
209
|
-
end
|
210
|
-
|
211
|
-
def invalid_command_error_message
|
212
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:invalid_command])
|
213
|
-
end
|
214
|
-
|
215
|
-
def wrong_password_error_message
|
216
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:password])
|
217
|
-
end
|
218
|
-
|
219
|
-
def user_not_found_error_message
|
220
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:user_not_found])
|
221
|
-
end
|
222
|
-
|
223
|
-
def not_logged_in_message
|
224
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:user_not_logged_in])
|
225
|
-
end
|
226
|
-
|
227
|
-
def user_created_message
|
228
|
-
bot.api.send_message(chat_id: msg.chat.id, text: success_messages[:user_created])
|
229
|
-
end
|
230
132
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
user.update(current_chat_id: chat.id)
|
237
|
-
bot.api.send_message(chat_id: msg.chat.id, text: success_messages[:chat_created])
|
238
|
-
end
|
239
|
-
|
240
|
-
def chat_creation_failed_message
|
241
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:chat_creation_failed])
|
242
|
-
end
|
243
|
-
|
244
|
-
def no_chat_selected
|
245
|
-
bot.api.send_message(chat_id: msg.chat.id,
|
246
|
-
text: error_messages[:no_chat_selected])
|
247
|
-
end
|
248
|
-
|
249
|
-
def chat_not_found_message
|
250
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:chat_not_found])
|
251
|
-
end
|
252
|
-
|
253
|
-
def error_log(err)
|
254
|
-
if err.message.to_s.include?("Bad Request: message is too long")
|
255
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:message_history_too_long])
|
256
|
-
else
|
257
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:something_went_wrong])
|
133
|
+
def stop_event
|
134
|
+
register_event_action("stop", visitor.id) unless visitor.tel_user
|
135
|
+
register_user_action("stop", visitor.tel_user.id) if visitor.tel_user
|
136
|
+
send_message commom_messages[:stop], msg.chat.id
|
137
|
+
bot.api.leave_chat(chat_id: msg.chat.id)
|
258
138
|
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def user
|
262
|
-
@user ||= User.find_by(telegram_id: msg.chat.id)
|
263
|
-
end
|
264
|
-
|
265
|
-
def bot
|
266
|
-
@bot ||= Telegram::Bot::Client.new(telegram_token)
|
267
|
-
end
|
268
139
|
|
269
|
-
|
270
|
-
|
271
|
-
|
140
|
+
def nil_event
|
141
|
+
register_event_action("nil", visitor.id) unless visitor.tel_user
|
142
|
+
register_user_action("nil", visitor.tel_user.id) if visitor.tel_user
|
143
|
+
send_message error_messages[:nil], msg.chat.id
|
144
|
+
end
|
272
145
|
|
273
|
-
|
274
|
-
|
275
|
-
|
146
|
+
def audio_event
|
147
|
+
return not_logged_in_message unless user
|
148
|
+
return no_chat_selected_message if user.current_chat_id.nil?
|
149
|
+
|
150
|
+
register_user_action("audio", user.id)
|
151
|
+
user_audio = transcribe_file(telegram_audio_url)
|
152
|
+
message = Message.new(content: user_audio[:text], chat_id: user.current_chat_id, role: "user")
|
153
|
+
if message.save
|
154
|
+
ai_response = telegram_process_ai_voice(user_audio[:file])
|
155
|
+
telegram_send_voice_message(voice: ai_response[:voice], text: ai_response[:text])
|
156
|
+
delete_file ai_response[:voice]
|
157
|
+
else
|
158
|
+
send_message error_messages[:message_creation_error], msg.chat.id
|
159
|
+
end
|
160
|
+
end
|
276
161
|
end
|
277
162
|
end
|
@@ -15,38 +15,7 @@ module ChatgptAssistant
|
|
15
15
|
@openai_api_key = openai_api_key
|
16
16
|
end
|
17
17
|
|
18
|
-
def download_audio(audio_url)
|
19
|
-
audio_conn = Faraday.new(url: audio_url)
|
20
|
-
File.open(dl_file_name, "wb") do |file|
|
21
|
-
file.write(audio_conn.get.body)
|
22
|
-
end
|
23
|
-
FFMPEG::Movie.new(dl_file_name).transcode(file_name)
|
24
|
-
File.delete(dl_file_name)
|
25
|
-
end
|
26
|
-
|
27
|
-
def header
|
28
|
-
{
|
29
|
-
"Content-Type": "multipart/form-data",
|
30
|
-
"Authorization": "Bearer #{openai_api_key}"
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
def payload
|
35
|
-
{
|
36
|
-
"file": Faraday::UploadIO.new(file_name, "audio/mp3"),
|
37
|
-
"model": "whisper-1"
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
def transcribed_file_json
|
42
|
-
{
|
43
|
-
file_name: file_name,
|
44
|
-
text: JSON.parse(response.body)["text"]
|
45
|
-
}.to_json
|
46
|
-
end
|
47
|
-
|
48
18
|
def transcribe_audio(audio_url)
|
49
|
-
@audio_url = audio_url
|
50
19
|
download_audio(audio_url)
|
51
20
|
@response = conn.post("v1/audio/transcriptions", payload, header)
|
52
21
|
transcribed_file_json
|
@@ -54,6 +23,36 @@ module ChatgptAssistant
|
|
54
23
|
|
55
24
|
private
|
56
25
|
|
57
|
-
|
26
|
+
attr_reader :conn, :time,
|
27
|
+
:response, :dl_file_name, :file_name,
|
28
|
+
:ibm_api_key, :ibm_url, :openai_api_key
|
29
|
+
|
30
|
+
def download_audio(audio_url)
|
31
|
+
audio_conn = Faraday.new(url: audio_url)
|
32
|
+
File.binwrite(dl_file_name, audio_conn.get.body)
|
33
|
+
FFMPEG::Movie.new(dl_file_name).transcode(file_name)
|
34
|
+
File.delete(dl_file_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def header
|
38
|
+
{
|
39
|
+
"Content-Type": "multipart/form-data",
|
40
|
+
Authorization: "Bearer #{openai_api_key}"
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def payload
|
45
|
+
{
|
46
|
+
file: Faraday::UploadIO.new(file_name, "audio/mp3"),
|
47
|
+
model: "whisper-1"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def transcribed_file_json
|
52
|
+
{
|
53
|
+
file: file_name,
|
54
|
+
text: JSON.parse(response.body)["text"]
|
55
|
+
}
|
56
|
+
end
|
58
57
|
end
|
59
58
|
end
|
@@ -22,98 +22,94 @@ module ChatgptAssistant
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
attr_reader :openai_api_key, :ibm_api_key, :ibm_url, :aws_access_key_id, :aws_secret_access_key, :aws_region,
|
26
|
+
:config, :language, :voice
|
27
|
+
|
28
|
+
def faraday_instance
|
29
|
+
Faraday.new(url: "https://api.openai.com/") do |faraday|
|
30
|
+
faraday.request :multipart
|
31
|
+
faraday.request :url_encoded
|
32
|
+
faraday.adapter Faraday.default_adapter
|
33
|
+
end
|
33
34
|
end
|
34
|
-
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
def classify_mode
|
37
|
+
if ibm_mode?
|
38
|
+
@ibm_api_key = config.ibm_api_key
|
39
|
+
@ibm_url = config.ibm_url
|
40
|
+
@voice = send("#{language}_ibm_voice")
|
41
|
+
elsif aws_mode?
|
42
|
+
@aws_access_key_id = config.aws_access_key_id
|
43
|
+
@aws_secret_access_key = config.aws_secret_access_key
|
44
|
+
@aws_region = config.aws_region
|
45
|
+
@voice = send("#{language}_aws_voice")
|
46
|
+
end
|
46
47
|
end
|
47
|
-
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
49
|
+
def synthesize_text_aws(text)
|
50
|
+
time = Time.now.to_i
|
51
|
+
@time = Time.now.to_i
|
52
|
+
polly_client = Aws::Polly::Client.new(
|
53
|
+
access_key_id: aws_access_key_id,
|
54
|
+
secret_access_key: aws_secret_access_key,
|
55
|
+
region: aws_region
|
56
|
+
)
|
57
|
+
response = polly_client.synthesize_speech(
|
58
|
+
output_format: "mp3",
|
59
|
+
text: text,
|
60
|
+
voice_id: voice,
|
61
|
+
engine: "neural"
|
62
|
+
)
|
63
|
+
|
64
|
+
File.binwrite("voice/aws-#{time}.mp3", response.audio_stream.read)
|
65
|
+
"voice/aws-#{time}.mp3"
|
66
66
|
end
|
67
|
-
"voice/aws-#{time}.mp3"
|
68
|
-
end
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
def synthesize_text_ibm(text)
|
69
|
+
time = Time.now.to_i
|
70
|
+
authenticator = IBMWatson::Authenticators::IamAuthenticator.new(
|
71
|
+
apikey: ibm_api_key
|
72
|
+
)
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
text_to_speech = IBMWatson::TextToSpeechV1.new(
|
75
|
+
authenticator: authenticator
|
76
|
+
)
|
79
77
|
|
80
|
-
|
78
|
+
text_to_speech.service_url = ibm_url
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
80
|
+
audio_format = "audio/mp3"
|
81
|
+
audio = text_to_speech.synthesize(
|
82
|
+
text: text,
|
83
|
+
accept: audio_format,
|
84
|
+
voice: voice
|
85
|
+
).result
|
88
86
|
|
89
|
-
|
90
|
-
|
87
|
+
File.binwrite("voice/ibm-#{time}.mp3", audio)
|
88
|
+
"voice/ibm-#{time}.mp3"
|
91
89
|
end
|
92
|
-
"voice/ibm-#{time}.mp3"
|
93
|
-
end
|
94
90
|
|
95
|
-
|
96
|
-
|
97
|
-
|
91
|
+
def pt_aws_voice
|
92
|
+
"Vitoria"
|
93
|
+
end
|
98
94
|
|
99
|
-
|
100
|
-
|
101
|
-
|
95
|
+
def en_aws_voice
|
96
|
+
"Joanna"
|
97
|
+
end
|
102
98
|
|
103
|
-
|
104
|
-
|
105
|
-
|
99
|
+
def pt_ibm_voice
|
100
|
+
"pt-BR_IsabelaV3Voice"
|
101
|
+
end
|
106
102
|
|
107
|
-
|
108
|
-
|
109
|
-
|
103
|
+
def en_ibm_voice
|
104
|
+
"en-US_AllisonV3Voice"
|
105
|
+
end
|
110
106
|
|
111
|
-
|
112
|
-
|
113
|
-
|
107
|
+
def ibm_mode?
|
108
|
+
config.mode == "ibm"
|
109
|
+
end
|
114
110
|
|
115
|
-
|
116
|
-
|
117
|
-
|
111
|
+
def aws_mode?
|
112
|
+
config.mode == "aws"
|
113
|
+
end
|
118
114
|
end
|
119
115
|
end
|