chatgpt_assistant 0.1.6 → 0.1.8

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.env_sample +35 -10
  3. data/.rubocop.yml +14 -3
  4. data/Dockerfile +11 -5
  5. data/Gemfile +25 -23
  6. data/Gemfile.lock +123 -85
  7. data/README.md +22 -22
  8. data/Rakefile +1 -0
  9. data/docker-compose.yml +8 -4
  10. data/exe/chatgpt_assistant +1 -1
  11. data/lib/chatgpt_assistant/audio_synthesis.rb +54 -15
  12. data/lib/{bots → chatgpt_assistant/bots}/application_bot.rb +0 -6
  13. data/lib/chatgpt_assistant/bots/discord/actions.rb +103 -0
  14. data/lib/chatgpt_assistant/bots/discord/auth.rb +36 -0
  15. data/lib/chatgpt_assistant/bots/discord/bot.rb +29 -0
  16. data/lib/chatgpt_assistant/bots/discord/chat_actions.rb +33 -0
  17. data/lib/chatgpt_assistant/bots/discord/events.rb +138 -0
  18. data/lib/chatgpt_assistant/bots/discord/validations.rb +38 -0
  19. data/lib/chatgpt_assistant/bots/discord/voice_actions.rb +33 -0
  20. data/lib/chatgpt_assistant/bots/discord/voice_checkers.rb +35 -0
  21. data/lib/chatgpt_assistant/bots/discord_bot.rb +41 -0
  22. data/lib/chatgpt_assistant/bots/helpers/messenger_helper.rb +16 -0
  23. data/lib/{bots → chatgpt_assistant/bots}/jobs/register_job.rb +2 -2
  24. data/lib/chatgpt_assistant/bots/mailers/account_mailer.rb +30 -0
  25. data/lib/chatgpt_assistant/bots/mailers/application_mailer.rb +21 -0
  26. data/lib/chatgpt_assistant/bots/services/new_chat_service.rb +59 -0
  27. data/lib/chatgpt_assistant/bots/services/register_service.rb +45 -0
  28. data/lib/chatgpt_assistant/bots/telegram/actions.rb +54 -0
  29. data/lib/chatgpt_assistant/bots/telegram/auth.rb +40 -0
  30. data/lib/chatgpt_assistant/bots/telegram/bot.rb +17 -0
  31. data/lib/chatgpt_assistant/bots/telegram/chat_actions.rb +30 -0
  32. data/lib/chatgpt_assistant/bots/telegram/events.rb +121 -0
  33. data/lib/chatgpt_assistant/bots/telegram/events_controller.rb +48 -0
  34. data/lib/chatgpt_assistant/bots/telegram/permissions.rb +48 -0
  35. data/lib/chatgpt_assistant/bots/telegram/validations.rb +55 -0
  36. data/lib/chatgpt_assistant/bots/telegram/voice_actions.rb +36 -0
  37. data/lib/chatgpt_assistant/bots/telegram_bot.rb +44 -0
  38. data/lib/chatgpt_assistant/chatter.rb +10 -2
  39. data/lib/chatgpt_assistant/config.rb +7 -1
  40. data/lib/chatgpt_assistant/default_messages.rb +10 -4
  41. data/lib/chatgpt_assistant/error.rb +9 -0
  42. data/lib/chatgpt_assistant/migrations.rb +5 -0
  43. data/lib/chatgpt_assistant/models.rb +20 -0
  44. data/lib/chatgpt_assistant/version.rb +1 -1
  45. data/lib/chatgpt_assistant.rb +5 -3
  46. metadata +35 -25
  47. data/.env_prod_sample +0 -18
  48. data/docker-compose.prod.yml +0 -34
  49. data/lib/bots/discord_bot.rb +0 -182
  50. data/lib/bots/helpers/authentication_helper.rb +0 -48
  51. data/lib/bots/helpers/discord_helper.rb +0 -124
  52. data/lib/bots/helpers/discord_voice_helper.rb +0 -50
  53. data/lib/bots/helpers/messenger_helper.rb +0 -133
  54. data/lib/bots/helpers/telegram_helper.rb +0 -73
  55. data/lib/bots/helpers/telegram_voice_helper.rb +0 -33
  56. data/lib/bots/helpers/validation_helper.rb +0 -38
  57. data/lib/bots/helpers/visit_helper.rb +0 -28
  58. data/lib/bots/services/new_chat_service.rb +0 -34
  59. data/lib/bots/services/register_service.rb +0 -36
  60. data/lib/bots/telegram_bot.rb +0 -180
  61. /data/lib/{bots → chatgpt_assistant/bots}/helpers/audio_helper.rb +0 -0
  62. /data/lib/{bots → chatgpt_assistant/bots}/helpers/file_helper.rb +0 -0
  63. /data/lib/{bots → chatgpt_assistant/bots}/helpers/search_helper.rb +0 -0
  64. /data/lib/{bots → chatgpt_assistant/bots}/jobs/new_chat_job.rb +0 -0
  65. /data/lib/{bots → chatgpt_assistant/bots}/jobs/voice_connect_job.rb +0 -0
  66. /data/lib/{bots → chatgpt_assistant/bots}/services/voice_connect_service.rb +0 -0
data/Rakefile CHANGED
@@ -4,6 +4,7 @@
4
4
  require "rspec/core/rake_task"
5
5
  require "lucy_dockerunner"
6
6
  require "awesome_chatgpt_actors"
7
+ require "dotenv/load"
7
8
 
8
9
  RSpec::Core::RakeTask.new(:spec)
9
10
 
data/docker-compose.yml CHANGED
@@ -18,29 +18,33 @@ services:
18
18
  build: .
19
19
  command: bash -c "exe/chatgpt_bot telegram"
20
20
  volumes:
21
- - .:/chatgpt_assistant
21
+ - .:/assistant
22
22
  environment:
23
23
  POSTGRES_HOST: db
24
24
  env_file:
25
25
  - .env
26
26
  depends_on:
27
27
  - db
28
+ - redis
29
+ - sidekiq
28
30
  discord:
29
31
  build: .
30
32
  command: bash -c "exe/chatgpt_bot discord"
31
33
  volumes:
32
- - .:/chatgpt_assistant
34
+ - .:/assistant
33
35
  environment:
34
36
  POSTGRES_HOST: db
35
37
  env_file:
36
38
  - .env
37
39
  depends_on:
38
40
  - db
41
+ - redis
42
+ - sidekiq
39
43
  sidekiq:
40
44
  build: .
41
45
  command: bash -c "exe/chatgpt_bot sidekiq"
42
46
  volumes:
43
- - .:/chatgpt_assistant
47
+ - .:/assistant
44
48
  environment:
45
49
  POSTGRES_HOST: db
46
50
  env_file:
@@ -49,4 +53,4 @@ services:
49
53
  - db
50
54
  - redis
51
55
  volumes:
52
- postgres:
56
+ postgres:
@@ -26,7 +26,7 @@ gem_dir = Gem::Specification.find_by_name("chatgpt_assistant").gem_dir
26
26
  `cp #{gem_dir}/#{file} #{path}`
27
27
  end
28
28
 
29
- %w[docker-compose.yml docker-compose.prod.yml Dockerfile LICENSE LICENSE.txt].each do |file|
29
+ %w[docker-compose.yml Dockerfile LICENSE LICENSE.txt].each do |file|
30
30
  `cp #{gem_dir}/#{file} #{path}`
31
31
  end
32
32
 
@@ -6,31 +6,28 @@ module ChatgptAssistant
6
6
  class AudioSynthesis
7
7
  def initialize(config)
8
8
  @config = config
9
- @openai_api_key = config.openai_api_key
10
9
  @language = config.language
11
- @conn = faraday_instance
12
10
  classify_mode
13
11
  end
14
12
 
15
13
  def synthesize_text(text)
14
+ @text = text
16
15
  if ibm_mode?
17
- synthesize_text_ibm(text)
16
+ synthesize_text_ibm
18
17
  elsif aws_mode?
19
- synthesize_text_aws(text)
18
+ synthesize_text_aws
19
+ elsif azure_mode?
20
+ synthesize_text_azure
20
21
  end
21
22
  end
22
23
 
23
24
  private
24
25
 
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
26
+ attr_reader :ibm_api_key, :ibm_url, :aws_access_key_id, :aws_secret_access_key, :aws_region,
27
+ :config, :language, :voice, :azure_speech_url, :azure_speech_key, :text
27
28
 
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
29
+ def conn(url)
30
+ Faraday.new(url: url)
34
31
  end
35
32
 
36
33
  def classify_mode
@@ -43,12 +40,14 @@ module ChatgptAssistant
43
40
  @aws_secret_access_key = config.aws_secret_access_key
44
41
  @aws_region = config.aws_region
45
42
  @voice = send("#{language}_aws_voice")
43
+ elsif azure_mode?
44
+ @azure_speech_url = config.azure_speech_url
45
+ @azure_speech_key = config.azure_speech_key
46
46
  end
47
47
  end
48
48
 
49
- def synthesize_text_aws(text)
49
+ def synthesize_text_aws
50
50
  time = Time.now.to_i
51
- @time = Time.now.to_i
52
51
  polly_client = Aws::Polly::Client.new(
53
52
  access_key_id: aws_access_key_id,
54
53
  secret_access_key: aws_secret_access_key,
@@ -65,7 +64,7 @@ module ChatgptAssistant
65
64
  "voice/aws-#{time}.mp3"
66
65
  end
67
66
 
68
- def synthesize_text_ibm(text)
67
+ def synthesize_text_ibm
69
68
  time = Time.now.to_i
70
69
  authenticator = IBMWatson::Authenticators::IamAuthenticator.new(
71
70
  apikey: ibm_api_key
@@ -88,6 +87,25 @@ module ChatgptAssistant
88
87
  "voice/ibm-#{time}.mp3"
89
88
  end
90
89
 
90
+ def synthesize_text_azure
91
+ @voice = send("#{language}_azure_voice")
92
+ time = Time.now.to_i
93
+ headers = {
94
+ "Ocp-Apim-Subscription-Key": azure_speech_key,
95
+ "Content-Type": "application/ssml+xml",
96
+ "X-Microsoft-OutputFormat": "audio-48khz-192kbitrate-mono-mp3",
97
+ "User-Agent": "curl"
98
+ }
99
+
100
+ response = conn(azure_speech_url).post do |req|
101
+ req.headers = headers
102
+ req.body = voice
103
+ end
104
+
105
+ File.binwrite("voice/azure-#{time}.mp3", response.body)
106
+ "voice/azure-#{time}.mp3"
107
+ end
108
+
91
109
  def pt_aws_voice
92
110
  "Vitoria"
93
111
  end
@@ -104,6 +122,23 @@ module ChatgptAssistant
104
122
  "en-US_AllisonV3Voice"
105
123
  end
106
124
 
125
+ def pt_azure_voice
126
+ <<~XML
127
+ <speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts"
128
+ xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="pt-BR">
129
+ <voice name="pt-BR-AntonioNeural">#{text}</voice>
130
+ </speak>
131
+ XML
132
+ end
133
+
134
+ def en_azure_voice
135
+ <<~XML
136
+ <speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
137
+ <voice name="en-US-JennyNeural">#{text}</voice>
138
+ </speak>
139
+ XML
140
+ end
141
+
107
142
  def ibm_mode?
108
143
  config.mode == "ibm"
109
144
  end
@@ -111,5 +146,9 @@ module ChatgptAssistant
111
146
  def aws_mode?
112
147
  config.mode == "aws"
113
148
  end
149
+
150
+ def azure_mode?
151
+ config.mode == "azure"
152
+ end
114
153
  end
115
154
  end
@@ -2,11 +2,8 @@
2
2
 
3
3
  # helpers
4
4
  require_relative "helpers/messenger_helper"
5
- require_relative "helpers/authentication_helper"
6
- require_relative "helpers/visit_helper"
7
5
  require_relative "helpers/audio_helper"
8
6
  require_relative "helpers/search_helper"
9
- require_relative "helpers/validation_helper"
10
7
  require_relative "helpers/file_helper"
11
8
 
12
9
  # jobs
@@ -23,11 +20,8 @@ module ChatgptAssistant
23
20
  # This class is responsible to contain the shared attributes and methods
24
21
  class ApplicationBot
25
22
  include MessengerHelper
26
- include AuthenticationHelper
27
- include VisitHelper
28
23
  include AudioHelper
29
24
  include SearchHelper
30
- include ValidationHelper
31
25
  include FileHelper
32
26
 
33
27
  def initialize(config)
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module Actions
7
+ def login_action
8
+ user_email, user_password = message.split(":")
9
+ case discord_user_auth(user_email, user_password, evnt.user.id)
10
+ when "user not found"
11
+ send_message error_messages[:user_not_found]
12
+ when "wrong password"
13
+ send_message error_messages[:wrong_password]
14
+ when find_user(email: user_email).email
15
+ send_message success_messages[:user_logged_in]
16
+ end
17
+ end
18
+
19
+ def start_action
20
+ fields = %w[login start help new_chat sl_chat ask list hist connect disconnect speak]
21
+
22
+ values_hash = {
23
+ login: "Account login, use: #{discord_prefix}login email:password",
24
+ start: "Start the bot, use: #{discord_prefix}start",
25
+ help: "Show this message, use: #{discord_prefix}help",
26
+ new_chat: "Create a new chat, use: #{discord_prefix}new_chat chat_name",
27
+ sl_chat: "Select a chat, use: #{discord_prefix}sl_chat chat_name",
28
+ ask: "Ask a question, use: #{discord_prefix}ask question",
29
+ list: "List all chats, use: #{discord_prefix}list",
30
+ hist: "Show chat history, use: #{discord_prefix}hist",
31
+ connect: "Connect to voice channel, use: #{discord_prefix}connect",
32
+ disconnect: "Disconnect from voice channel, use: #{discord_prefix}disconnect",
33
+ speak: "Speak in voice channel, use: #{discord_prefix}speak question"
34
+ }
35
+
36
+ embed = Discordrb::Webhooks::Embed.new(
37
+ title: "Hello, #{evnt.user.name}!",
38
+ description: "I'm ChatGPT Assistant, see my commands below:",
39
+ color: "00FF00",
40
+ fields: fields.map { |field| { name: field, value: values_hash[field.to_sym] } }
41
+ )
42
+ evnt.respond nil, false, embed
43
+ end
44
+
45
+ def help_action
46
+ start_action
47
+ end
48
+
49
+ def list_action
50
+ chats = user.chats
51
+
52
+ embed = Discordrb::Webhooks::Embed.new(
53
+ title: "Hello, #{evnt.user.name}!",
54
+ description: "Your chats:",
55
+ color: "00FF00",
56
+ fields: chats.map { |field| { name: field.title, value: field.actor || "No prompt" } }
57
+ )
58
+
59
+ evnt.respond nil, false, embed
60
+ end
61
+
62
+ def hist_action
63
+ messages = Message.where(chat_id: chat.id).order(:created_at)
64
+ messages.each { |m| send_message "#{m.role} - #{m.content}\n#{m.created_at.strftime("%d/%m/%Y %H:%M")}" }
65
+ "This is the end of the chat history"
66
+ end
67
+
68
+ def sl_chat_action(chat_to_select)
69
+ @chat = user.chat_by_title(chat_to_select)
70
+ send_message error_messages[:chat_not_found] if chat.nil?
71
+ user.update(current_chat_id: chat.id) if chat
72
+ send_message success_messages[:chat_selected] if chat
73
+ end
74
+
75
+ def create_chat_action
76
+ title = evnt.message.content.split[1..].join(" ")
77
+ mode = nil
78
+ if title.include? ":"
79
+ mode = title.split(":").last.to_i
80
+ title = title.split(":").first
81
+ end
82
+ actors = AwesomeChatgptActors::CastControl.actors
83
+ return send_message "invalid mode" unless (mode.to_i >= 1 && mode.to_i <= actors.size + 1) || mode.nil?
84
+ return send_message "invalid chat title" if title.nil? || title.empty?
85
+ return send_message "chat title already exists" if user.chat_by_title(title)
86
+
87
+ actor_name = actors[mode.to_i - 1] if mode
88
+ actor = AwesomeChatgptActors::Actor.new(role: actor_name, language: config.language) if actor_name
89
+ chat = Chat.new(user_id: user.id, status: 0, title: title, actor: actor_name, prompt: actor.prompt) if actor
90
+ chat = Chat.new(user_id: user.id, status: 0, title: title) unless actor
91
+ return send_message "Something went wrong", msg.chat.id unless chat
92
+
93
+ chat.save ? chat_created_message(chat) : send_message(error_messages[:chat_creation])
94
+ end
95
+
96
+ def discord_created(chat)
97
+ evnt.respond "Intructions sended to actor:\n#{chat.prompt}" unless chat.actor.nil?
98
+ evnt.respond success_messages[:chat_created] if evnt.present?
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module Auth
7
+ def discord_visited?(user_id)
8
+ return unless evnt
9
+
10
+ visitor = Visitor.find_by(discord_id: user_id, name: evnt.user.name)
11
+ if visitor.nil?
12
+ Visitor.create(discord_id: user_id, name: evnt.user.name)
13
+ else
14
+ visitor
15
+ end
16
+ end
17
+
18
+ def discord_user_auth(email, password, discord_id)
19
+ user = find_user(email: email)
20
+ return "user not found" unless user
21
+ return "wrong passwords" if password.nil?
22
+
23
+ user.valid_password?(password) ? discord_user_access(discord_id, user.email) : "wrong password"
24
+ end
25
+
26
+ def discord_user_access(discord_id, user_email)
27
+ other_access = where_user(discord_id: discord_id)
28
+ other_access&.each { |access| access.update(discord_id: nil) }
29
+ user = find_user(email: user_email)
30
+ user.update(discord_id: discord_id)
31
+ user.email
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module Bot
7
+ def bot
8
+ @bot ||= Discordrb::Commands::CommandBot.new(
9
+ token: discord_token,
10
+ client_id: discord_client_id,
11
+ prefix: discord_prefix
12
+ )
13
+ end
14
+
15
+ def user
16
+ @user = find_user(discord_id: evnt.user.id)
17
+ end
18
+
19
+ def bot_init
20
+ at_exit { bot.stop }
21
+ bot.run
22
+ rescue StandardError => e
23
+ Error.create(message: e.message, backtrace: e.backtrace)
24
+ retry
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module ChatActions
7
+ def ask_action
8
+ @chat = Chat.where(id: user.current_chat_id).last
9
+ send_message error_messages[:chat_not_found] if chat.nil?
10
+ @message = Message.new(chat_id: chat.id, content: message, role: "user") if chat
11
+ (message.save ? answer_action : send_message(error_messages[:message_not_saved])) if chat
12
+ end
13
+
14
+ def private_message_action
15
+ @chat = Chat.where(id: user.current_chat_id).last
16
+ send_message error_messages[:chat_not_found] if chat.nil?
17
+ @message = Message.new(chat_id: chat.id, content: message, role: "user") if chat
18
+ (message.save ? answer_action : send_message(error_messages[:message_not_saved])) if chat
19
+ end
20
+
21
+ def answer_action
22
+ response = chatter.chat(message.content, chat.id, error_messages[:something_went_wrong])
23
+ send_message response
24
+ end
25
+
26
+ def send_message(text)
27
+ messages = parse_message(text, 2000)
28
+ messages.each { |m| evnt.respond m }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module Events
7
+ def start_event
8
+ bot.command :start do |event|
9
+ @evnt = event
10
+ @user = event.user
11
+ start_action
12
+ "Ok"
13
+ end
14
+ end
15
+
16
+ def login_event
17
+ bot.command :login do |event|
18
+ @message = event.message.content.split[1]
19
+ @evnt = event
20
+ message.nil? ? event.respond(common_messages[:login]) : login_action
21
+ "OK"
22
+ end
23
+ end
24
+
25
+ def list_event
26
+ bot.command :list do |event|
27
+ @evnt = event
28
+ list_action if valid_for_list_action?
29
+ "OK"
30
+ end
31
+ end
32
+
33
+ def hist_event
34
+ bot.command :hist do |event|
35
+ @evnt = event
36
+ @chat = user.current_chat
37
+ event.respond error_messages[:chat_not_found] if chat.nil? && user
38
+ hist_action if user && chat
39
+ "OK"
40
+ end
41
+ end
42
+
43
+ def help_event
44
+ bot.command :help do |event|
45
+ @evnt = event
46
+ help_action
47
+ "OK"
48
+ end
49
+ end
50
+
51
+ def new_chat_event
52
+ bot.command :new_chat do |event|
53
+ @evnt = event
54
+ event.respond error_messages[:user_not_logged_in] if user.nil?
55
+ event.respond error_messages[:account_not_verified] if user && !user.active?
56
+ create_chat_action if user&.active?
57
+ "OK"
58
+ end
59
+ end
60
+
61
+ def sl_chat_event
62
+ bot.command :sl_chat do |event|
63
+ @evnt = event
64
+ chat_to_select = event.message.content.split[1..].join(" ")
65
+ event.respond error_messages[:user_not_logged_in] if user.nil?
66
+ event.respond error_messages[:account_not_verified] if user && !user.active?
67
+ sl_chat_action(chat_to_select) if user&.active?
68
+ "OK"
69
+ end
70
+ end
71
+
72
+ def ask_event
73
+ bot.command :ask do |event|
74
+ @evnt = event
75
+ @message = event.message.content.split[1..].join(" ")
76
+ event.respond error_messages[:user_not_logged_in] if user.nil?
77
+ event.respond error_messages[:account_not_verified] if user && !user.active?
78
+ ask_action if user&.active?
79
+ "OK"
80
+ end
81
+ end
82
+
83
+ def voice_connect_event
84
+ bot.command :connect do |event|
85
+ @evnt = event
86
+ if user && !user.active?
87
+ event.respond error_messages[:account_not_verified]
88
+ elsif user&.current_chat_id.nil?
89
+ event.respond error_messages[:no_chat_selected]
90
+ elsif user&.current_chat_id
91
+ @chat = Chat.find(user.current_chat_id)
92
+ voice_connect_checker_action
93
+ voice_connection_checker_action
94
+ bot.voice_connect(event.user.voice_channel)
95
+ else
96
+ event.respond error_messages[:user_not_logged_in]
97
+ end
98
+ "OK"
99
+ end
100
+ end
101
+
102
+ def voice_disconnect_event
103
+ bot.command :disconnect do |event|
104
+ @evnt = event
105
+ disconnect_checker_action
106
+ disconnect_action if user && event.user.voice_channel && event.voice
107
+ "OK"
108
+ end
109
+ end
110
+
111
+ def speak_event
112
+ bot.command :speak do |event|
113
+ @evnt = event
114
+ @message = event.message.content.split[1..].join(" ")
115
+ @chat = user.current_chat
116
+ speak_connect_checker_action
117
+ speak_connection_checker_action
118
+ ask_to_speak_action if user && event.user.voice_channel && event.voice && !chat.nil?
119
+ "OK"
120
+ end
121
+ end
122
+
123
+ def private_message_event
124
+ bot.message do |event|
125
+ @evnt = event
126
+ @visitor = discord_visited?(@evnt.user.id)
127
+ next if discord_next_action?
128
+
129
+ @message = event.message.content
130
+ @chat = user.current_chat if user
131
+ private_message_action if user && !chat.nil?
132
+ "OK"
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module Validations
7
+ def discord_next_action?
8
+ return true if evnt.channel.type != 1 && evnt.channel.name != "ai-spaces"
9
+
10
+ %w[login register start help new_chat sl_chat ask
11
+ list hist connect disconnect speak].each do |action|
12
+ return true if evnt.message.content.include?("#{discord_prefix}#{action}")
13
+ end
14
+ false
15
+ end
16
+
17
+ def discord_voice_bot_disconnected?
18
+ user && evnt.user.voice_channel && !evnt.voice && !chat.nil?
19
+ end
20
+
21
+ def discord_voice_bot_connected?
22
+ user && evnt.user.voice_channel && evnt.voice && !chat.nil?
23
+ end
24
+
25
+ def visitor_user?
26
+ visitor&.dis_user.nil?
27
+ end
28
+
29
+ def valid_for_list_action?
30
+ evnt.respond(error_messages[:user_not_logged_in]) if user.nil?
31
+ evnt.respond(error_messages[:account_not_verified]) unless user.active?
32
+ evnt.respond(error_messages[:chat_not_found]) if user.chats.count.zero? && user.active?
33
+ !user.nil? && user.active? && user.chats.count.positive?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module VoiceActions
7
+ def ask_to_speak_action
8
+ Message.create(chat_id: chat.id, content: message, role: "user", discord_message_id: evnt.message.id)
9
+ response = chatter.chat(message, chat.id, error_messages[:something_went_wrong])
10
+ audio_path = synthesis.synthesize_text(response)
11
+ speak_answer_action(audio_path, response)
12
+ end
13
+
14
+ def speak_answer_action(audio_path, response)
15
+ send_message response
16
+ evnt.voice.play_file(audio_path)
17
+ delete_file audio_path
18
+ "OK"
19
+ end
20
+
21
+ def discord_voice_bot_connect
22
+ bot.voice_connect(evnt.user.voice_channel) if discord_voice_bot_disconnected?
23
+ discord_voice_bot_connected? ? "Connected to voice channel" : "Error connecting to voice channel"
24
+ end
25
+
26
+ def disconnect_action
27
+ bot.voice_destroy(evnt.user.voice_channel)
28
+ "Disconnected from voice channel"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Discord
6
+ module VoiceCheckers
7
+ def voice_connect_checker_action
8
+ send_message error_messages[:user_not_logged_in] if user.nil?
9
+ send_message error_messages[:chat_not_found] if user && chat.nil?
10
+ end
11
+
12
+ def voice_connection_checker_action
13
+ send_message error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
14
+ send_message error_messages[:bot_already_connected] if evnt.voice && user
15
+ end
16
+
17
+ def speak_connect_checker_action
18
+ send_message error_messages[:user_not_logged_in] if user.nil?
19
+ send_message error_messages[:chat_not_found] if user && evnt.user.voice_channel && evnt.voice && chat.nil?
20
+ end
21
+
22
+ def speak_connection_checker_action
23
+ send_message error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
24
+ send_message error_messages[:bot_not_in_voice_channel] if !evnt.voice && user
25
+ end
26
+
27
+ def disconnect_checker_action
28
+ send_message error_messages[:user_not_logged_in] if user.nil?
29
+ send_message error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
30
+ send_message error_messages[:user_not_connected] if !evnt.voice && user
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end