chatgpt_assistant 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.env_sample +16 -7
  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 +15 -18
  8. data/Rakefile +1 -0
  9. data/docker-compose.yml +8 -4
  10. data/exe/chatgpt_assistant +1 -1
  11. data/lib/{bots → chatgpt_assistant/bots}/application_bot.rb +0 -6
  12. data/lib/chatgpt_assistant/bots/discord/actions.rb +104 -0
  13. data/lib/chatgpt_assistant/bots/discord/auth.rb +36 -0
  14. data/lib/chatgpt_assistant/bots/discord/bot.rb +29 -0
  15. data/lib/chatgpt_assistant/bots/discord/chat_actions.rb +33 -0
  16. data/lib/chatgpt_assistant/bots/discord/events.rb +138 -0
  17. data/lib/chatgpt_assistant/bots/discord/validations.rb +38 -0
  18. data/lib/chatgpt_assistant/bots/discord/voice_actions.rb +33 -0
  19. data/lib/chatgpt_assistant/bots/discord/voice_checkers.rb +35 -0
  20. data/lib/chatgpt_assistant/bots/discord_bot.rb +42 -0
  21. data/lib/chatgpt_assistant/bots/helpers/messenger_helper.rb +16 -0
  22. data/lib/{bots → chatgpt_assistant/bots}/jobs/register_job.rb +2 -2
  23. data/lib/chatgpt_assistant/bots/mailers/account_mailer.rb +30 -0
  24. data/lib/chatgpt_assistant/bots/mailers/application_mailer.rb +21 -0
  25. data/lib/chatgpt_assistant/bots/services/new_chat_service.rb +59 -0
  26. data/lib/chatgpt_assistant/bots/services/register_service.rb +45 -0
  27. data/lib/chatgpt_assistant/bots/telegram/actions.rb +54 -0
  28. data/lib/chatgpt_assistant/bots/telegram/auth.rb +40 -0
  29. data/lib/chatgpt_assistant/bots/telegram/bot.rb +17 -0
  30. data/lib/chatgpt_assistant/bots/telegram/chat_actions.rb +30 -0
  31. data/lib/chatgpt_assistant/bots/telegram/events.rb +120 -0
  32. data/lib/chatgpt_assistant/bots/telegram/events_controller.rb +48 -0
  33. data/lib/chatgpt_assistant/bots/telegram/permissions.rb +48 -0
  34. data/lib/chatgpt_assistant/bots/telegram/validations.rb +55 -0
  35. data/lib/chatgpt_assistant/bots/telegram/voice_actions.rb +36 -0
  36. data/lib/chatgpt_assistant/bots/telegram_bot.rb +44 -0
  37. data/lib/chatgpt_assistant/chatter.rb +10 -2
  38. data/lib/chatgpt_assistant/config.rb +4 -1
  39. data/lib/chatgpt_assistant/default_messages.rb +10 -4
  40. data/lib/chatgpt_assistant/error.rb +9 -0
  41. data/lib/chatgpt_assistant/migrations.rb +5 -0
  42. data/lib/chatgpt_assistant/models.rb +20 -0
  43. data/lib/chatgpt_assistant/version.rb +1 -1
  44. data/lib/chatgpt_assistant.rb +5 -3
  45. metadata +34 -24
  46. data/.env_prod_sample +0 -18
  47. data/docker-compose.prod.yml +0 -34
  48. data/lib/bots/discord_bot.rb +0 -182
  49. data/lib/bots/helpers/authentication_helper.rb +0 -48
  50. data/lib/bots/helpers/discord_helper.rb +0 -124
  51. data/lib/bots/helpers/discord_voice_helper.rb +0 -50
  52. data/lib/bots/helpers/messenger_helper.rb +0 -133
  53. data/lib/bots/helpers/telegram_helper.rb +0 -73
  54. data/lib/bots/helpers/telegram_voice_helper.rb +0 -33
  55. data/lib/bots/helpers/validation_helper.rb +0 -38
  56. data/lib/bots/helpers/visit_helper.rb +0 -28
  57. data/lib/bots/services/new_chat_service.rb +0 -34
  58. data/lib/bots/services/register_service.rb +0 -36
  59. data/lib/bots/telegram_bot.rb +0 -180
  60. /data/lib/{bots → chatgpt_assistant/bots}/helpers/audio_helper.rb +0 -0
  61. /data/lib/{bots → chatgpt_assistant/bots}/helpers/file_helper.rb +0 -0
  62. /data/lib/{bots → chatgpt_assistant/bots}/helpers/search_helper.rb +0 -0
  63. /data/lib/{bots → chatgpt_assistant/bots}/jobs/new_chat_job.rb +0 -0
  64. /data/lib/{bots → chatgpt_assistant/bots}/jobs/voice_connect_job.rb +0 -0
  65. /data/lib/{bots → chatgpt_assistant/bots}/services/voice_connect_service.rb +0 -0
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ # This class is responsible to background the new chat service
5
+ class NewChatService
6
+ def initialize(chat_title, user_id, chat_id, config)
7
+ @chat_title = chat_title
8
+ @user_id = user_id
9
+ @chat_id = chat_id
10
+ @config = config
11
+ end
12
+
13
+ def telegram_async
14
+ TelegramBot.new(@config)
15
+ end
16
+
17
+ def actors
18
+ @actors ||= AwesomeChatgptActors::CastControl.actors
19
+ end
20
+
21
+ def actor
22
+ @actor_name = actors[@actor_mode.to_i - 1] if @actor_mode
23
+ @actor = AwesomeChatgptActors::Actor.new(role: @actor_name, language: @config.language) if @actor_name
24
+ end
25
+
26
+ def chat
27
+ @chat = Chat.new(title: @chat_title, user_id: @user_id, status: 0, actor: @actor_name, prompt: @actor.prompt) if !@actor.nil? && @actor_name
28
+ @chat = Chat.new(title: @chat_title, user_id: @user_id, status: 0) unless @actor_name
29
+ end
30
+
31
+ def parse_title
32
+ return @chat_title.strip! unless @chat_title.include?("actor:")
33
+
34
+ @actor_mode = @chat_title.split("actor:")[1].strip
35
+ @chat_title = @chat_title.split("actor:")[0].strip
36
+ end
37
+
38
+ def call
39
+ raise NilError if @chat_title.nil?
40
+ raise NilError if @user_id.nil?
41
+ raise NilError if @chat_id.nil?
42
+
43
+ parse_title
44
+
45
+ raise InvalidModeError unless (@actor_mode.to_i >= 1 && @actor_mode.to_i <= actors.size + 1) || @actor_mode.nil?
46
+ raise InvalidChatTitleError if @chat_title.nil? || @chat_title.empty?
47
+ raise ChatAlreadyExistsError if Chat.find_by(title: @chat_title)
48
+
49
+ if chat.save
50
+ telegram_async.send_message("Chat created succesfully", @chat_id)
51
+ else
52
+ raise ChatAlreadyExistsError if Chat.find_by(title: @chat_title)
53
+ raise NilError if chat.errors[:title].any?
54
+ end
55
+ rescue ChatAlreadyExistsError, NilError => e
56
+ telegram_async.send_message(e.message, @chat_id)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ # This class is responsible to background the register service
5
+ class RegisterService
6
+ def initialize(email, password, name, chat_id)
7
+ @name = name
8
+ @email = email
9
+ @password = password
10
+ @chat_id = chat_id
11
+ @config = Config.new
12
+ @config.db_connection
13
+ end
14
+
15
+ def call
16
+ return if user_already_exists?
17
+
18
+ @user = User.new(email: @email, password: @password, telegram_id: @chat_id, name: @name)
19
+ @user.save ? success_message : error_message
20
+ rescue UserAlreadyExistsError, WrongEmailError, WrongPasswordError => e
21
+ telegram_async.send_message(e.message, @chat_id)
22
+ end
23
+
24
+ private
25
+
26
+ def telegram_async
27
+ TelegramBot.new(@config)
28
+ end
29
+
30
+ def success_message
31
+ confirmation_token = @user.encrypt_token
32
+ telegram_async.send_message("Registration successful! Check your email for confirmation.", @chat_id)
33
+ AccountMailer.register_email(@user, confirmation_token).deliver_now
34
+ end
35
+
36
+ def error_message
37
+ raise WrongEmailError if @user.errors[:email].any?
38
+ raise WrongPasswordError if @user.errors[:password].any?
39
+ end
40
+
41
+ def user_already_exists?
42
+ raise UserAlreadyExistsError if User.find_by(email: @email)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Actions
7
+ def telegram_user_create(visitor_id, email, password)
8
+ visitor = Visitor.find_by(id: visitor_id)
9
+ return false unless visitor
10
+
11
+ visitor.tel_user.update(telegram_id: nil) if visitor.tel_user.present?
12
+ user = User.new(telegram_id: visitor.telegram_id, email: email, password: password)
13
+ user.save ? user.email : user.errors.full_messages
14
+ end
15
+
16
+ def telegram_send_start_message
17
+ send_message common_messages[:start], msg.chat.id
18
+ help_message = help_messages.join("\n").to_s
19
+ send_message help_message, msg.chat.id
20
+ send_message common_messages[:start_helper], msg.chat.id
21
+ send_message common_messages[:start_sec_helper], msg.chat.id
22
+ end
23
+
24
+ def telegram_create_chat
25
+ text = msg.text
26
+ title = text.split("/").last
27
+ mode = nil
28
+ if title.include?(":")
29
+ mode = title.split(":").last
30
+ title = title.split(":").first
31
+ end
32
+ actor_modes = AwesomeChatgptActors::CastControl.actors
33
+ return send_message "invalid mode", msg.chat.id unless (mode.to_i >= 1 && mode.to_i <= actor_modes.size + 1) || mode.nil?
34
+ return send_message "invalid chat title", msg.chat.id if title.nil? || title.empty?
35
+ return send_message "You already have a chat with this title", msg.chat.id if user.chat_by_title(title)
36
+
37
+ actor_name = actor_modes[mode.to_i - 1] if mode
38
+ actor = AwesomeChatgptActors::Actor.new(prompt_type: actor_name) if actor_name
39
+ chat = Chat.new(user_id: user.id, status: 0, title: title, actor: actor_name, prompt: actor.prompt) if actor
40
+ chat = Chat.new(user_id: user.id, status: 0, title: title) unless actor
41
+ return send_message "Something went wrong", msg.chat.id unless chat
42
+
43
+ chat.save ? chat_created_message(chat) : send_message(chat_id: msg.chat.id, text: error_messages[:chat_creation_failed])
44
+ end
45
+
46
+ def chat_created_message(chat)
47
+ bot.api.send_message(chat_id: msg.chat.id, text: "Intructions sended to actor:\n#{chat.prompt}") unless chat.actor.nil?
48
+ bot.api.send_message(chat_id: msg.chat.id, text: "Response from assistant:\n#{chat.messages[1].content}") unless chat.actor.nil?
49
+ bot.api.send_message(chat_id: msg.chat.id, text: success_messages[:chat_created]) if bot.respond_to?(:api)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Auth
7
+ def authenticate_user(email, password)
8
+ case telegram_user_auth(email, password, msg.chat.id)
9
+ when "user not found"
10
+ raise UserNotFoundError
11
+ when "wrong password"
12
+ raise WrongPasswordError
13
+ when email
14
+ send_message(chat_id: msg.chat.id, text: success_messages[:user_logged_in])
15
+ end
16
+ end
17
+
18
+ def telegram_user_auth(email, password, telegram_id)
19
+ return "wrong password" if password.nil?
20
+
21
+ visitor_access = find_visitor(telegram_id: telegram_id)
22
+ return "something went wrong" unless visitor_access
23
+
24
+ new_access = find_user(email: email)
25
+ return "user not found" unless new_access
26
+
27
+ user.valid_password?(password) ? telegram_user_access(visitor_access, new_access) : "wrong password"
28
+ end
29
+
30
+ def telegram_user_access(visitor, new_access)
31
+ other_access = where_user(telegram_id: visitor.telegram_id)
32
+ other_access&.each { |access| access.update(telegram_id: nil) } if other_access&.class == Array
33
+ other_access&.update(telegram_id: nil) if other_access&.class == User
34
+ new_access.update(telegram_id: visitor.telegram_id)
35
+ new_access.email
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Bot
7
+ def bot
8
+ @bot ||= ::Telegram::Bot::Client.new(telegram_token, logger: Logger.new($stderr))
9
+ end
10
+
11
+ def user
12
+ @user = find_user(telegram_id: msg.chat.id)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module ChatActions
7
+ def chat_if_exists
8
+ chat = Chat.find_by(user_id: user.id, id: user.current_chat_id)
9
+ chat ? chat_success(chat.id) : send_message(chat_id: msg.chat.id, text: error_messages[:no_chat_selected])
10
+ end
11
+
12
+ def chat_success(chat_id)
13
+ user_message = Message.new(chat_id: chat_id, content: msg.text, role: "user")
14
+ if user_message&.save
15
+ text = chatter.chat(msg.text, chat_id, error_messages[:something_went_wrong])
16
+ mess = parse_message(text, 4096)
17
+ mess.each { |m| send_message m, msg.chat.id }
18
+ else
19
+ send_message error_messages[:something_went_wrong], msg.chat.id
20
+ end
21
+ end
22
+
23
+ def send_message(text, chat_id)
24
+ messages = parse_message(text, 4096)
25
+ messages.each { |m| bot.api.send_message(chat_id: chat_id, text: m) }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Events
7
+ def start_event
8
+ telegram_send_start_message
9
+ end
10
+
11
+ def help_event
12
+ help_messages.each { |m| send_message m, msg.chat.id }
13
+ end
14
+
15
+ def hist_event
16
+ hist_allowed?
17
+
18
+ user.chat_history.each do |m|
19
+ send_message m, msg.chat.id
20
+ end
21
+ rescue NoChatSelectedError, UserNotLoggedInError, NoMessagesFoundedError, AccountNotVerifiedError => e
22
+ send_message e.message, msg.chat.id
23
+ end
24
+
25
+ def list_event
26
+ list_allowed?
27
+
28
+ send_message common_messages[:chat_list], msg.chat.id
29
+ chats_str = ""
30
+ user.chats.each_with_index { |c, i| chats_str += "Chat #{i + 1} - #{c.title}\n" }
31
+ send_message chats_str, msg.chat.id
32
+ rescue NoChatsFoundedError, UserNotLoggedInError, AccountNotVerifiedError => e
33
+ send_message e.message, msg.chat.id
34
+ end
35
+
36
+ def confirm_account_event
37
+ raise UserNotLoggedInError if user.nil?
38
+
39
+ user_info = msg.text.split("/* ").last
40
+ name, token = user_info.split(":")
41
+ send_message "#{name} - #{token}", msg.chat.id
42
+ if user_confirmed?
43
+ send_message success_messages[:account_confirmed], msg.chat.id
44
+ else
45
+ send_message error_messages[:account_not_confirmed], msg.chat.id
46
+ end
47
+ rescue UserNotLoggedInError => e
48
+ send_message e.message, msg.chat.id
49
+ end
50
+
51
+ def login_event
52
+ raise UserLoggedInError if user
53
+
54
+ user_info = msg.text.split("/").last
55
+ email, password = user_info.split(":")
56
+ authenticate_user(email, password)
57
+ rescue UserNotFoundError, WrongPasswordError, UserLoggedInError => e
58
+ send_message e.message, msg.chat.id
59
+ end
60
+
61
+ def register_event
62
+ user_info = msg.text.split("/").last
63
+ email, password = register_allowed?(user_info)
64
+ name = msg.from.first_name || "Anonymous"
65
+
66
+ RegisterJob.perform_async(email, password, name, visitor.telegram_id)
67
+ rescue NoRegisterInfoError, UserLoggedInError => e
68
+ send_message e.message, msg.chat.id
69
+ end
70
+
71
+ def sign_out_event
72
+ raise UserNotLoggedInError if user.nil?
73
+
74
+ user.update(telegram_id: nil)
75
+ send_message success_messages[:user_logged_out], msg.chat.id
76
+ rescue UserNotLoggedInError => e
77
+ send_message e.message, msg.chat.id
78
+ end
79
+
80
+ def new_chat_event
81
+ common_allowed?
82
+ NewChatJob.perform_async(msg.text.split("/").last, user.id, msg.chat.id)
83
+ rescue UserNotLoggedInError, AccountNotVerifiedError => e
84
+ send_message e.message, msg.chat.id
85
+ end
86
+
87
+ def select_chat_event
88
+ common_allowed?
89
+ title = msg.text.split("/").last
90
+ chat = user.chat_by_title(title)
91
+ select_allowed?(chat)
92
+
93
+ send_message success_messages[:chat_selected], msg.chat.id
94
+ rescue UserNotLoggedInError, ChatNotFoundError, AccountNotVerifiedError => e
95
+ send_message e.message, msg.chat.id
96
+ end
97
+
98
+ def audio_event
99
+ audio_allowed?
100
+ user_audio = transcribe_file(telegram_audio_url)
101
+ message = Message.new(content: user_audio[:text], chat_id: user.current_chat_id, role: "user")
102
+ raise MessageNotCreatedError unless message.save
103
+
104
+ ai_response = telegram_process_ai_voice(user_audio[:file])
105
+ telegram_send_voice_message(voice: ai_response[:voice], text: ai_response[:text])
106
+ delete_file ai_response[:voice]
107
+ rescue UserNotLoggedInError, NoChatSelectedError, MessageNotCreatedError, AccountNotVerifiedError => e
108
+ send_message e.message, msg.chat.id
109
+ end
110
+
111
+ def telegram_chat_event
112
+ common_allowed?
113
+ chat_if_exists
114
+ rescue UserNotLoggedInError, AccountNotVerifiedError => e
115
+ send_message e.message, msg.chat.id
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module EventsController
7
+ def auth_events
8
+ return login_event if msg.text.include?("login/")
9
+ return register_event if msg.text.include?("register/")
10
+ return sign_out_event if msg.text.include?("sign_out/")
11
+ return confirm_account_event if msg.text.include?("confirm/* ")
12
+ end
13
+
14
+ def action_events
15
+ return auth_events if auth_event?
16
+ return new_chat_event if msg.text.include?("new_chat/")
17
+ return select_chat_event if msg.text.include?("sl_chat/")
18
+ return telegram_chat_event unless telegram_actions?
19
+
20
+ raise InvalidCommandError
21
+ rescue InvalidCommandError => e
22
+ send_message e.message, msg.chat.id
23
+ end
24
+
25
+ def text_events
26
+ case msg.text
27
+ when "/start"
28
+ start_event
29
+ when "/help"
30
+ help_event
31
+ when "/hist"
32
+ hist_event
33
+ when "/list"
34
+ list_event
35
+ when "/stop"
36
+ stop_event
37
+ when nil
38
+ raise NilError
39
+ else
40
+ action_events
41
+ end
42
+ rescue NilError => e
43
+ send_message e.message, msg.chat.id
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Permissions
7
+ def hist_allowed?
8
+ raise UserNotLoggedInError if user.nil?
9
+ raise AccountNotVerifiedError unless user.active?
10
+ raise NoChatSelectedError if user.current_chat.nil?
11
+ raise NoMessagesFoundedError if user.current_chat.messages.count.zero?
12
+ end
13
+
14
+ def list_allowed?
15
+ raise UserNotLoggedInError if user.nil?
16
+ raise AccountNotVerifiedError unless user.active?
17
+ raise NoChatsFoundedError if user.chats.count.zero?
18
+ end
19
+
20
+ def register_allowed?(user_info)
21
+ raise NoRegisterInfoError if user_info.nil?
22
+ raise UserLoggedInError if user
23
+
24
+ email, password = user_info.split(":")
25
+ raise NoRegisterEmailError if email.nil? || password.nil?
26
+
27
+ [email, password]
28
+ end
29
+
30
+ def common_allowed?
31
+ raise UserNotLoggedInError if user.nil?
32
+ raise AccountNotVerifiedError unless user.active?
33
+ end
34
+
35
+ def select_allowed?(chat)
36
+ raise ChatNotFoundError if chat.nil?
37
+ raise ChatNotFoundError unless user.update(current_chat_id: chat.id)
38
+ end
39
+
40
+ def audio_allowed?
41
+ raise UserNotLoggedInError if user.nil?
42
+ raise AccountNotVerifiedError unless user.active?
43
+ raise NoChatSelectedError if user.current_chat.nil?
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module Validations
7
+ def telegram_actions?
8
+ msg.text.include?("new_chat/") || msg.text.include?("sl_chat/") || msg.text.include?("login/") || msg.text.include?("register/")
9
+ end
10
+
11
+ def telegram_text_or_audio?
12
+ msg.respond_to?(:text) || msg.respond_to?(:audio) || msg.respond_to?(:voice)
13
+ end
14
+
15
+ def telegram_message_has_text?
16
+ msg.text.present?
17
+ end
18
+
19
+ def telegram_message_has_audio?
20
+ msg.audio.present? || msg.voice.present?
21
+ end
22
+
23
+ def telegram_visited?(chat_id)
24
+ return unless msg
25
+
26
+ visitor = Visitor.find_by(telegram_id: chat_id, name: msg.from.first_name)
27
+ if visitor.nil?
28
+ Visitor.create(telegram_id: chat_id, name: msg.from.first_name)
29
+ else
30
+ visitor
31
+ end
32
+ end
33
+
34
+ def visitor_user?
35
+ visitor&.tel_user.nil?
36
+ end
37
+
38
+ def valid_for_list_action?
39
+ send_message(chat_id: msg.chat.id, text: error_messages[:user_not_logged_in]) if user.nil?
40
+ send_message(chat_id: msg.chat.id, text: error_messages[:account_not_verified]) unless user.active?
41
+ send_message(chat_id: msg.chat.id, text: error_messages[:chat_not_found]) if user.chats.count.zero? && user.active?
42
+ !user.nil? && user.active? && user.chats.count.positive?
43
+ end
44
+
45
+ def auth_event?
46
+ msg.text.include?("login/") || msg.text.include?("register/") || msg.text.include?("sign_out/") || msg.text.include?("confirm/* ")
47
+ end
48
+
49
+ def user_confirmed?
50
+ user.name == name && user.confirm_account(token)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatgptAssistant
4
+ module Bots
5
+ module Telegram
6
+ module VoiceActions
7
+ def telegram_audio_info
8
+ bot.api.get_file(file_id: telegram_audio.file_id)
9
+ end
10
+
11
+ def telegram_audio_url
12
+ "https://api.telegram.org/file/bot#{telegram_token}/#{telegram_audio_info["result"]["file_path"]}"
13
+ end
14
+
15
+ def telegram_audio
16
+ msg.audio || msg.voice
17
+ end
18
+
19
+ def telegram_process_ai_voice(user_audio)
20
+ ai_text = chatter.chat(user_audio["text"], user.current_chat_id, error_messages[:something_went_wrong])
21
+ ai_voice = synthesis.synthesize_text(ai_text)
22
+ {
23
+ voice: ai_voice,
24
+ text: ai_text
25
+ }
26
+ end
27
+
28
+ def telegram_send_voice_message(voice: nil, text: nil)
29
+ messages = parse_message text, 4096
30
+ bot.api.send_voice(chat_id: msg.chat.id, voice: Faraday::UploadIO.new(voice, "audio/mp3"))
31
+ messages.each { |message| send_message message, msg.chat.id }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "telegram/bot"
4
+ require_relative "telegram/auth"
5
+ require_relative "telegram/actions"
6
+ require_relative "telegram/events"
7
+ require_relative "telegram/chat_actions"
8
+ require_relative "telegram/validations"
9
+ require_relative "telegram/voice_actions"
10
+ require_relative "telegram/permissions"
11
+ require_relative "telegram/events_controller"
12
+
13
+ module ChatgptAssistant
14
+ # This class is responsible for the telegram bot features
15
+ class TelegramBot < ApplicationBot
16
+ def start
17
+ bot.listen do |message|
18
+ @msg = message
19
+ @visitor = telegram_visited?(@msg.chat.id)
20
+ next unless telegram_text_or_audio?
21
+
22
+ text_events if telegram_message_has_text?
23
+ audio_event if telegram_message_has_audio?
24
+ end
25
+ rescue StandardError => e
26
+ Error.create(message: e.message, backtrace: e.backtrace)
27
+ retry
28
+ end
29
+
30
+ private
31
+
32
+ attr_accessor :msg, :visitor, :chat, :chat_id
33
+
34
+ include Bots::Telegram::Bot
35
+ include Bots::Telegram::Auth
36
+ include Bots::Telegram::Actions
37
+ include Bots::Telegram::Events
38
+ include Bots::Telegram::ChatActions
39
+ include Bots::Telegram::Validations
40
+ include Bots::Telegram::VoiceActions
41
+ include Bots::Telegram::Permissions
42
+ include Bots::Telegram::EventsController
43
+ end
44
+ end
@@ -17,7 +17,7 @@ module ChatgptAssistant
17
17
  @response = request(message)
18
18
  @json = JSON.parse(response.body)
19
19
 
20
- return no_response_error if json["choices"].empty?
20
+ return no_response_error if json["choices"] && json["choices"].empty?
21
21
  return bot_offline_error if response.status != 200
22
22
 
23
23
  text = json["choices"][0]["message"]["content"]
@@ -57,7 +57,8 @@ module ChatgptAssistant
57
57
  end
58
58
 
59
59
  def request_params(message)
60
- messages = Message.where(chat_id: chat_id).order(id: :asc).last(10)
60
+ messages_from_chat = Message.where(chat_id: chat_id)
61
+ messages = messages_from_chat.order(id: :asc).last(10)
61
62
  messages = if messages.empty?
62
63
  [{ role: "user", content: message }]
63
64
  else
@@ -66,6 +67,13 @@ module ChatgptAssistant
66
67
  content: mess.content }
67
68
  end
68
69
  end
70
+
71
+ first_message = messages_from_chat.order(id: :asc).first
72
+ system_message = first_message if first_message&.role == "system"
73
+ if system_message && Message.where(chat_id: chat_id).count > 10
74
+ messages.unshift({ role: system_message.role,
75
+ content: system_message.content })
76
+ end
69
77
  {
70
78
  model: "gpt-3.5-turbo",
71
79
  messages: messages,
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_record"
4
4
  require "active_model"
5
+ require "action_mailer"
5
6
  require_relative "migrations"
6
7
  require "fileutils"
7
8
 
@@ -30,7 +31,9 @@ module ChatgptAssistant
30
31
 
31
32
  attr_reader :openai_api_key, :telegram_token, :discord_token, :ibm_api_key, :ibm_url,
32
33
  :aws_access_key_id, :aws_secret_access_key, :aws_region, :mode, :language,
33
- :discord_client_id, :discord_public_key, :env_type, :discord_prefix
34
+ :discord_client_id, :discord_public_key, :env_type, :discord_prefix,
35
+ :smtp_address, :smtp_port, :smtp_domain, :smtp_user_name, :smtp_password,
36
+ :smtp_authentication, :smtp_enable_starttls_auto
34
37
 
35
38
  def db_connection
36
39
  ActiveRecord::Base.establish_connection(