chatgpt_assistant 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env_sample +18 -0
- data/.rspec +3 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +147 -0
- data/Dockerfile +15 -0
- data/Gemfile +47 -0
- data/Gemfile.lock +299 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +77 -0
- data/Rakefile +15 -0
- data/deploy.sh +10 -0
- data/deploy_and_build.sh +11 -0
- data/docker-compose.prod.yml +34 -0
- data/docker-compose.yml +34 -0
- data/exe/chatgpt_assistant +43 -0
- data/exe/chatgpt_bot +16 -0
- data/lib/bots/application_bot.rb +119 -0
- data/lib/bots/discord_bot.rb +304 -0
- data/lib/bots/telegram_bot.rb +279 -0
- data/lib/chatgpt_assistant/audio_recognition.rb +54 -0
- data/lib/chatgpt_assistant/audio_synthesis.rb +124 -0
- data/lib/chatgpt_assistant/chatter.rb +84 -0
- data/lib/chatgpt_assistant/chatter_logger.rb +18 -0
- data/lib/chatgpt_assistant/config.rb +59 -0
- data/lib/chatgpt_assistant/default_messages.rb +144 -0
- data/lib/chatgpt_assistant/migrations.rb +57 -0
- data/lib/chatgpt_assistant/models.rb +45 -0
- data/lib/chatgpt_assistant/version.rb +5 -0
- data/lib/chatgpt_assistant.rb +57 -0
- data/logs/.keep +0 -0
- data/sig/chatgpt_assistant.rbs +4 -0
- data/voice/.keep +0 -0
- metadata +87 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 JesusGautamah
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# ChatGPT Assistant
|
2
|
+
|
3
|
+
This Ruby gem provides an easy way to initialize a client for Telegram and Discord bots using the ChatGPT API, audio transcription, IBM Cloud Text to Speech, and AWS Polly, creating an assistant that can answer questions in text and voice and have a conversation with the user.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
- Ruby > 2.6.0
|
8
|
+
- Docker
|
9
|
+
- Docker Compose
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
To install the gem, run:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
gem install chatgpt_assistant
|
17
|
+
```
|
18
|
+
|
19
|
+
Then, edit the .env_sample file to include the necessary credentials and rename it to .env. Run bundle install to install the necessary dependencies.
|
20
|
+
|
21
|
+
Remember to edit docker-compose.prod.yml when deploying to production.
|
22
|
+
|
23
|
+
Alternatively, you can clone/fork this repo to use it as you wish.
|
24
|
+
|
25
|
+
### Installation as a gem example
|
26
|
+
|
27
|
+
```bash
|
28
|
+
gem install chatgpt_assistant
|
29
|
+
chatgpt_assistant PATH_TO_FOLDER
|
30
|
+
cd PATH_TO_FOLDER
|
31
|
+
cp .env_sample .env
|
32
|
+
bundle install
|
33
|
+
```
|
34
|
+
|
35
|
+
## Installation as a repo
|
36
|
+
Run in your terminal:
|
37
|
+
```bash
|
38
|
+
git clone https://github.com/JesusGautamah/chatgpt_assistant.git
|
39
|
+
cd chatgpt_assistant
|
40
|
+
cp .env_sample .env
|
41
|
+
bundle install
|
42
|
+
```
|
43
|
+
|
44
|
+
Make sure to run bundle before using the Lucy Dockerunner rake tasks.
|
45
|
+
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
You can start the Docker Compose services required for the gem using the rake tasks provided by the Lucy Dockerunner gem. These tasks include compose:up, compose:down, compose:status, compose:shell, compose:restart, and others listed previously.
|
49
|
+
|
50
|
+
For example, to start the services, run:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
rake compose:up
|
54
|
+
```
|
55
|
+
|
56
|
+
|
57
|
+
To stop the services, run:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
rake compose:down
|
61
|
+
```
|
62
|
+
|
63
|
+
After starting the Docker Compose services, you can use the features of the gem to create a chat assistant that responds to questions in both text and voice using the services mentioned above.
|
64
|
+
|
65
|
+
## More commands at https://github.com/JesusGautamah/lucy_dockerunner
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/JesusGautamah/chatgpt_assistant. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/JesusGautamah/chatgpt_assistant/blob/master/CODE_OF_CONDUCT.md).
|
70
|
+
|
71
|
+
## License
|
72
|
+
|
73
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
74
|
+
|
75
|
+
## Code of Conduct
|
76
|
+
|
77
|
+
Everyone interacting in the ChatgptAssistant project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/JesusGautamah/chatgpt_assistant/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
require "lucy_dockerunner"
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
require "rubocop/rake_task"
|
10
|
+
|
11
|
+
RuboCop::RakeTask.new
|
12
|
+
|
13
|
+
task default: %i[spec rubocop]
|
14
|
+
|
15
|
+
LucyDockerunner.load_tasks
|
data/deploy.sh
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin bash
|
2
|
+
|
3
|
+
# This script is used to deploy the application to the server
|
4
|
+
|
5
|
+
echo "Deploying the application to the server..."
|
6
|
+
cd chatgpt_assistant
|
7
|
+
git pull
|
8
|
+
sudo docker compose up -d
|
9
|
+
sudo docker compose restart
|
10
|
+
echo "Deployed the application to the server"
|
data/deploy_and_build.sh
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin bash
|
2
|
+
|
3
|
+
# This script is used to deploy the application to the server
|
4
|
+
|
5
|
+
echo "Deploying the application to the server..."
|
6
|
+
cd chatgpt_assistant
|
7
|
+
git pull
|
8
|
+
sudo docker compose build
|
9
|
+
sudo docker compose up -d
|
10
|
+
sudo docker compose restart
|
11
|
+
echo "Deployed the application to the server"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
version: "3.3"
|
2
|
+
services:
|
3
|
+
db:
|
4
|
+
image: postgres:12.2
|
5
|
+
ports:
|
6
|
+
- "5432:5432"
|
7
|
+
volumes:
|
8
|
+
- ./db_data:/var/lib/postgresql/data
|
9
|
+
env_file:
|
10
|
+
- .env
|
11
|
+
telegram:
|
12
|
+
build: .
|
13
|
+
command: bash -c "exe/chatgpt_bot telegram"
|
14
|
+
volumes:
|
15
|
+
- .:/chatgpt_assistant
|
16
|
+
environment:
|
17
|
+
POSTGRES_HOST: db
|
18
|
+
env_file:
|
19
|
+
- .env
|
20
|
+
depends_on:
|
21
|
+
- db
|
22
|
+
discord:
|
23
|
+
build: .
|
24
|
+
command: bash -c "exe/chatgpt_bot discord"
|
25
|
+
volumes:
|
26
|
+
- .:/chatgpt_assistant
|
27
|
+
environment:
|
28
|
+
POSTGRES_HOST: db
|
29
|
+
env_file:
|
30
|
+
- .env
|
31
|
+
depends_on:
|
32
|
+
- db
|
33
|
+
volumes:
|
34
|
+
postgres:
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
version: "3.3"
|
2
|
+
services:
|
3
|
+
db:
|
4
|
+
image: postgres:12.2
|
5
|
+
ports:
|
6
|
+
- "5432:5432"
|
7
|
+
volumes:
|
8
|
+
- ./db_data:/var/lib/postgresql/data
|
9
|
+
env_file:
|
10
|
+
- .env
|
11
|
+
telegram:
|
12
|
+
build: .
|
13
|
+
command: bash -c "exe/chatgpt_bot telegram"
|
14
|
+
volumes:
|
15
|
+
- .:/chatgpt_assistant
|
16
|
+
environment:
|
17
|
+
POSTGRES_HOST: db
|
18
|
+
env_file:
|
19
|
+
- .env
|
20
|
+
depends_on:
|
21
|
+
- db
|
22
|
+
discord:
|
23
|
+
build: .
|
24
|
+
command: bash -c "exe/chatgpt_bot discord"
|
25
|
+
volumes:
|
26
|
+
- .:/chatgpt_assistant
|
27
|
+
environment:
|
28
|
+
POSTGRES_HOST: db
|
29
|
+
env_file:
|
30
|
+
- .env
|
31
|
+
depends_on:
|
32
|
+
- db
|
33
|
+
volumes:
|
34
|
+
postgres:
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
path = ARGV[0]
|
5
|
+
raise "Please specify the path to copy files to" if path.nil?
|
6
|
+
|
7
|
+
puts "Creating new chatgpt assistant at #{path}"
|
8
|
+
|
9
|
+
`mkdir -p #{path}`
|
10
|
+
|
11
|
+
raise "Path must be empty" unless Dir.empty?(path)
|
12
|
+
|
13
|
+
gem_dir = Gem::Specification.find_by_name("chatgpt_assistant").gem_dir
|
14
|
+
|
15
|
+
`cp -r #{gem_dir}/lib #{path}`
|
16
|
+
|
17
|
+
`mkdir -p #{path}/exe`
|
18
|
+
|
19
|
+
`cp #{gem_dir}/exe/chatgpt_bot #{path}/exe`
|
20
|
+
|
21
|
+
`mkdir -p #{path}/logs`
|
22
|
+
|
23
|
+
`mkdir -p #{path}/voice`
|
24
|
+
|
25
|
+
%w[Gemfile Gemfile.lock README.md Rakefile .env_sample .rubocop.yml .rspec].each do |file|
|
26
|
+
`cp #{gem_dir}/#{file} #{path}`
|
27
|
+
end
|
28
|
+
|
29
|
+
%w[docker-compose.yml docker-compose.prod.yml Dockerfile LICENSE LICENSE.txt].each do |file|
|
30
|
+
`cp #{gem_dir}/#{file} #{path}`
|
31
|
+
end
|
32
|
+
|
33
|
+
%w[/.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ /db_data /db_data/*
|
34
|
+
.rspec_status .env /logs/telegram_chatgpt.log /voice/audio* /voice/ibm* /voice/polly* /voice/aws*].each do |file_to_ignore|
|
35
|
+
`echo "#{file_to_ignore}" >> #{path}/.gitignore`
|
36
|
+
end
|
37
|
+
|
38
|
+
`cd #{path} && git init`
|
39
|
+
|
40
|
+
puts "Done! Now you can run 'cd #{path} && bundle install'"
|
41
|
+
puts "Build the docker image with 'rake compose:build'"
|
42
|
+
puts "Run the bot with 'rake compose:up'"
|
43
|
+
puts "For more information, see the README.md file"
|
data/exe/chatgpt_bot
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../lib/chatgpt_assistant"
|
5
|
+
|
6
|
+
puts "Starting Chatgpt Assistant"
|
7
|
+
puts "Bot Type: #{ARGV[0]}"
|
8
|
+
puts "Mode: #{ENV["MODE"]}"
|
9
|
+
case ARGV[0]
|
10
|
+
when "telegram"
|
11
|
+
ChatgptAssistant::Main.new("telegram").start
|
12
|
+
when "discord"
|
13
|
+
ChatgptAssistant::Main.new("discord").start
|
14
|
+
when "migrate"
|
15
|
+
ChatgptAssistant::Config.new.migrate
|
16
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ChatgptAssistant
|
4
|
+
# This class is responsible to contain the shared variables between the bot classes
|
5
|
+
class ApplicationBot
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
default_msg = DefaultMessages.new(@config.language)
|
9
|
+
@logger = ChatterLogger.new
|
10
|
+
@openai_api_key = @config.openai_api_key
|
11
|
+
@telegram_token = @config.telegram_token
|
12
|
+
@discord_token = @config.discord_token
|
13
|
+
@discord_client_id = @config.discord_client_id
|
14
|
+
@discord_prefix = @config.discord_prefix
|
15
|
+
@database = @config.db_connection
|
16
|
+
@mode = @config.mode
|
17
|
+
@commom_messages = default_msg.commom_messages
|
18
|
+
@error_messages = default_msg.error_messages
|
19
|
+
@success_messages = default_msg.success_messages
|
20
|
+
@help_messages = default_msg.help_messages
|
21
|
+
end
|
22
|
+
|
23
|
+
def chatter
|
24
|
+
@chatter ||= Chatter.new(openai_api_key)
|
25
|
+
end
|
26
|
+
|
27
|
+
def audio_recognition
|
28
|
+
@audio_recognition ||= AudioRecognition.new(openai_api_key)
|
29
|
+
end
|
30
|
+
|
31
|
+
def audio_synthesis
|
32
|
+
@audio_synthesis ||= AudioSynthesis.new(config)
|
33
|
+
end
|
34
|
+
|
35
|
+
def message_create(message, chat_id, role)
|
36
|
+
Message.create(content: message, chat_id: chat_id, role: role)
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_useremail(email)
|
40
|
+
User.find_by(email: email)
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_userdiscord(discord_id)
|
44
|
+
User.find_by(discord_id: discord_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_usertelegram(telegram_id)
|
48
|
+
User.find_by(telegram_id: telegram_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def valid_password?(user, password)
|
52
|
+
return false if password.nil?
|
53
|
+
|
54
|
+
salt = user.password_salt
|
55
|
+
password_hash = user.password_hash
|
56
|
+
|
57
|
+
BCrypt::Engine.hash_secret(password, salt) == password_hash
|
58
|
+
end
|
59
|
+
|
60
|
+
def auth_userdiscord(email, password, discord_id)
|
61
|
+
user = find_useremail(email)
|
62
|
+
return "user not found" unless user
|
63
|
+
return "wrong password" if password.nil?
|
64
|
+
|
65
|
+
valid_password?(user, password) ? user_disc_access(discord_id, user.email) : "wrong password"
|
66
|
+
end
|
67
|
+
|
68
|
+
def user_disc_access(discord_id, user_email)
|
69
|
+
last_access = find_userdiscord(discord_id)
|
70
|
+
new_access = find_useremail(user_email)
|
71
|
+
last_acess.update(discord_id: nil) if last_access && (last_access != new_access)
|
72
|
+
new_access.update(discord_id: discord_id)
|
73
|
+
new_access
|
74
|
+
end
|
75
|
+
|
76
|
+
def discord_user_create(discord_id, email, password, name)
|
77
|
+
user = User.new(discord_id: discord_id, email: email, password_hash: password, name: name)
|
78
|
+
last_access = find_userdiscord(discord_id)
|
79
|
+
last_access&.update(discord_id: nil)
|
80
|
+
user.save
|
81
|
+
end
|
82
|
+
|
83
|
+
def auth_usertelegram(email, password, telegram_id)
|
84
|
+
user = find_useremail(email)
|
85
|
+
return "user not found" unless user
|
86
|
+
return "wrong password" if password.nil?
|
87
|
+
|
88
|
+
valid_password?(user, password) ? user_tele_access(telegram_id, user.email) : "wrong password"
|
89
|
+
end
|
90
|
+
|
91
|
+
def user_tele_access(telegram_id, user_email)
|
92
|
+
last_access = find_usertelegram(telegram_id)
|
93
|
+
new_access = find_useremail(user_email)
|
94
|
+
last_acess.update(telegram_id: nil) if last_access && (last_access != new_access)
|
95
|
+
new_access.update(telegram_id: telegram_id)
|
96
|
+
new_access
|
97
|
+
end
|
98
|
+
|
99
|
+
def telegram_user_create(telegram_id, email, password, name)
|
100
|
+
user = User.new(telegram_id: telegram_id, email: email, password_hash: password, name: name)
|
101
|
+
last_access = find_usertelegram(telegram_id)
|
102
|
+
last_access&.update(telegram_id: nil)
|
103
|
+
user.save
|
104
|
+
end
|
105
|
+
|
106
|
+
def delete_all_voice_files
|
107
|
+
Dir.glob("voice/*").each do |file|
|
108
|
+
next if [".keep", "voice/.keep"].include?(file)
|
109
|
+
|
110
|
+
File.delete(file)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_reader :openai_api_key, :telegram_token, :database, :default_msg,
|
115
|
+
:logger, :mode, :config, :discord_token, :discord_client_id,
|
116
|
+
:discord_prefix, :commom_messages, :error_messages, :success_messages,
|
117
|
+
:help_messages
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ChatgptAssistant
|
4
|
+
# This class is responsible to handle the discord bot
|
5
|
+
class DiscordBot < ApplicationBot
|
6
|
+
def start
|
7
|
+
start_logs
|
8
|
+
start_event
|
9
|
+
login_event
|
10
|
+
register_event
|
11
|
+
list_event
|
12
|
+
hist_event
|
13
|
+
help_event
|
14
|
+
new_chat_event
|
15
|
+
sl_chat_event
|
16
|
+
ask_event
|
17
|
+
voice_connect_event
|
18
|
+
disconnect_event
|
19
|
+
speak_event
|
20
|
+
bot_init
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :message
|
26
|
+
attr_accessor :evnt, :user, :chats, :chat
|
27
|
+
|
28
|
+
def bot
|
29
|
+
@bot ||= Discordrb::Commands::CommandBot.new(
|
30
|
+
token: discord_token,
|
31
|
+
client_id: discord_client_id,
|
32
|
+
prefix: discord_prefix
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def start_logs
|
37
|
+
logger.log("Starting Discord bot")
|
38
|
+
logger.log("Discord Prefix: #{discord_prefix}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_event
|
42
|
+
bot.command :start do |event|
|
43
|
+
@evnt = event
|
44
|
+
@user = event.user
|
45
|
+
start_action
|
46
|
+
end
|
47
|
+
logger.log("Start Event Configured")
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_action
|
51
|
+
logger.log("USER: #{user.username} - #{user.id}\n MESSAGE: #{event.message.content}")
|
52
|
+
evnt.respond commom_messages[:start]
|
53
|
+
evnt.respond commom_messages[:start_helper].gsub("register/", "gpt!register ")
|
54
|
+
evnt.respond commom_messages[:start_sec_helper].gsub("login/", "gpt!login ")
|
55
|
+
end
|
56
|
+
|
57
|
+
def login_event
|
58
|
+
bot.command :login do |event|
|
59
|
+
@message = event.message.content.split(" ")[1]
|
60
|
+
@evnt = event
|
61
|
+
message.nil? ? event.respond(commom_messages[:login]) : login_action
|
62
|
+
end
|
63
|
+
logger.log("Login Event Configured")
|
64
|
+
end
|
65
|
+
|
66
|
+
def login_action
|
67
|
+
user_email = message.split(":")[0]
|
68
|
+
user_password = message.split(":")[1]
|
69
|
+
case auth_userdiscord(user_email, user_password, evnt.user.id)
|
70
|
+
when "user not found"
|
71
|
+
logger.log("User not found: #{user_email}")
|
72
|
+
evnt.respond error_messages[:user_not_found]
|
73
|
+
when "wrong password"
|
74
|
+
logger.log("Wrong password: #{user_email}")
|
75
|
+
evnt.respond error_messages[:wrong_password]
|
76
|
+
when find_useremail(user_email)
|
77
|
+
logger.log("User logged in: #{user_email}")
|
78
|
+
evnt.respond success_messages[:user_logged_in]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def register_event
|
83
|
+
bot.command :register do |event|
|
84
|
+
@message = event.message.content.split(" ")[1]
|
85
|
+
@evnt = event
|
86
|
+
message.nil? ? event.respond(commom_messages[:register]): register_action
|
87
|
+
end
|
88
|
+
logger.log("Register Event Configured")
|
89
|
+
end
|
90
|
+
|
91
|
+
def register_action
|
92
|
+
user_email = message.split(":")[0]
|
93
|
+
user_password = message.split(":")[1]
|
94
|
+
find_useremail(user_email).nil? ? create_user_action(user_email, user_password) : evnt.respond(error_messages[:user_already_exists])
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_user_action(mail, pass)
|
98
|
+
logger.log("Creating user #{mail}")
|
99
|
+
id = evnt.user.id
|
100
|
+
name = evnt.user.username
|
101
|
+
discord_user_create(id, mail, pass, name) ? evnt.respond(success_messages[:user_created]) : evnt.respond(error_messages[:user_not_created])
|
102
|
+
end
|
103
|
+
|
104
|
+
def list_event
|
105
|
+
bot.command :list do |event|
|
106
|
+
@evnt = event
|
107
|
+
@user = User.find_by(discord_id: event.user.id)
|
108
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
109
|
+
|
110
|
+
@chats = Chat.where(user_id: user.id) if user
|
111
|
+
event.respond error_messages[:chat_not_found] if chats.empty? && user
|
112
|
+
|
113
|
+
list_action if user && !chats.empty?
|
114
|
+
end
|
115
|
+
logger.log("List Event Configured")
|
116
|
+
end
|
117
|
+
|
118
|
+
def list_action
|
119
|
+
chats_title = chats.map(&:title)
|
120
|
+
evnt.respond commom_messages[:chat_list]
|
121
|
+
evnt.respond chats_title.join("\n")
|
122
|
+
end
|
123
|
+
|
124
|
+
def hist_event
|
125
|
+
bot.command :hist do |event|
|
126
|
+
@evnt = event
|
127
|
+
@user = User.find_by(discord_id: event.user.id)
|
128
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
129
|
+
title = event.message.content.split(" ")[1 .. -1].join(" ")
|
130
|
+
@chat = Chat.find_by(user_id: user.id, title: title) if user
|
131
|
+
event.respond error_messages[:chat_not_found] if chat.nil? && user
|
132
|
+
hist_action if user && chat
|
133
|
+
end
|
134
|
+
logger.log("Hist Event Configured")
|
135
|
+
end
|
136
|
+
|
137
|
+
def hist_action
|
138
|
+
messages = Message.where(chat_id: chat.id).order(:created_at)
|
139
|
+
messages.each do |message|
|
140
|
+
evnt.respond "#{message.role} - #{message.content}\n#{message.created_at.strftime("%d/%m/%Y %H:%M")}"
|
141
|
+
end
|
142
|
+
"This is the end of the chat history"
|
143
|
+
end
|
144
|
+
|
145
|
+
def help_event
|
146
|
+
bot.command :help do |event|
|
147
|
+
@evnt = event
|
148
|
+
help_action
|
149
|
+
end
|
150
|
+
logger.log("Help Event Configured")
|
151
|
+
end
|
152
|
+
|
153
|
+
def help_action
|
154
|
+
message = help_messages.join("\n").gsub(" /", " gpt!")
|
155
|
+
.gsub("register/", "gpt!register ")
|
156
|
+
.gsub("login/", "gpt!login ")
|
157
|
+
.gsub("new_chat/", "gpt!new_chat/")
|
158
|
+
.gsub("sl_chat/", "gpt!sl_chat/")
|
159
|
+
evnt.respond message
|
160
|
+
end
|
161
|
+
|
162
|
+
def new_chat_event
|
163
|
+
bot.command :new_chat do |event|
|
164
|
+
@evnt = event
|
165
|
+
@user = User.find_by(discord_id: event.user.id)
|
166
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
167
|
+
create_chat_action if user
|
168
|
+
end
|
169
|
+
logger.log("New Chat Event Configured")
|
170
|
+
end
|
171
|
+
|
172
|
+
def create_chat_action
|
173
|
+
chat_title = event.message.content.split(" ")[1..].join(" ")
|
174
|
+
chat = Chat.new(user_id: user.id, title: chat_title, status: 0)
|
175
|
+
chat.save ? respond_with_success : evnt.respond(error_messages[:chat_creation])
|
176
|
+
end
|
177
|
+
|
178
|
+
def respond_with_success
|
179
|
+
user.update(current_chat_id: chat.id)
|
180
|
+
evnt.respond success_messages[:chat_created]
|
181
|
+
end
|
182
|
+
|
183
|
+
def sl_chat_event
|
184
|
+
bot.command :sl_chat do |event|
|
185
|
+
@evnt = event
|
186
|
+
chat_to_select = event.message.content.split(" ")[1..].join(" ")
|
187
|
+
|
188
|
+
@user = User.find_by(discord_id: event.user.id)
|
189
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
190
|
+
|
191
|
+
sl_chat_action(chat_to_select) if user
|
192
|
+
end
|
193
|
+
logger.log("SL Chat Event Configured")
|
194
|
+
end
|
195
|
+
|
196
|
+
def sl_chat_action(chat_to_select)
|
197
|
+
@chat = Chat.find_by(title: chat_to_select, user_id: user.id)
|
198
|
+
evnt.respond error_messages[:chat_not_found] if chat.nil?
|
199
|
+
user.update(current_chat_id: chat.id) if chat
|
200
|
+
evnt.respond success_messages[:chat_selected] if chat
|
201
|
+
end
|
202
|
+
|
203
|
+
def ask_event
|
204
|
+
bot.command :ask do |event|
|
205
|
+
@evnt = event
|
206
|
+
@message = event.message.content.split(" ")[1..].join(" ")
|
207
|
+
@user = User.find_by(discord_id: event.user.id)
|
208
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
209
|
+
ask_action if user
|
210
|
+
end
|
211
|
+
logger.log("Ask Event Configured")
|
212
|
+
end
|
213
|
+
|
214
|
+
def ask_action
|
215
|
+
@chat = Chat.where(id: user.current_chat_id).last
|
216
|
+
evnt.respond error_messages[:chat_not_found] if chat.nil?
|
217
|
+
@message = Message.new(chat_id: chat.id, content: message, role: "user") if chat
|
218
|
+
(message.save ? answer_action : evnt.respond(error_messages[:message_not_saved])) if chat
|
219
|
+
end
|
220
|
+
|
221
|
+
def answer_action
|
222
|
+
response = chatter.chat(message.content, chat.id)
|
223
|
+
evnt.respond response
|
224
|
+
end
|
225
|
+
|
226
|
+
def voice_connect_event
|
227
|
+
bot.command :connect do |event|
|
228
|
+
@evnt = event
|
229
|
+
@user = User.find_by(discord_id: event.user.id)
|
230
|
+
@chat = Chat.where(id: user.current_chat_id).last
|
231
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
232
|
+
event.respond error_messages[:chat_not_found] if user && chat.nil?
|
233
|
+
event.respond error_messages[:user_not_in_voice_channel] if event.user.voice_channel.nil? && user
|
234
|
+
event.respond error_messages[:bot_already_connected] if event.voice && user
|
235
|
+
bot.voice_connect(event.user.voice_channel) if bot_disconnected?
|
236
|
+
"Connected to voice channel" if bot_connected?
|
237
|
+
end
|
238
|
+
logger.log("Voice Connect Event Configured")
|
239
|
+
end
|
240
|
+
|
241
|
+
def bot_disconnected?
|
242
|
+
user && evnt.user.voice_channel && !evnt.voice && !chat.nil?
|
243
|
+
end
|
244
|
+
|
245
|
+
def bot_connected?
|
246
|
+
user && evnt.user.voice_channel && evnt.voice && !chat.nil?
|
247
|
+
end
|
248
|
+
|
249
|
+
def disconnect_event
|
250
|
+
bot.command :disconnect do |event|
|
251
|
+
@evnt = event
|
252
|
+
@user = User.find_by(discord_id: event.user.id)
|
253
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
254
|
+
event.respond error_messages[:user_not_in_voice_channel] if event.user.voice_channel.nil? && user
|
255
|
+
event.respond error_messages[:user_not_connected] if !event.voice && user
|
256
|
+
disconnect_action if user && event.user.voice_channel && event.voice
|
257
|
+
end
|
258
|
+
logger.log("Disconnect Event Configured")
|
259
|
+
end
|
260
|
+
|
261
|
+
def disconnect_action
|
262
|
+
logger.log("Disconnecting from voice channel: #{evnt.user.voice_channel.name}")
|
263
|
+
bot.voice_destroy(event.user.voice_channel)
|
264
|
+
logger.log("Disconnected from voice channel: #{evnt.user.voice_channel.name}")
|
265
|
+
"Disconnected from voice channel"
|
266
|
+
end
|
267
|
+
|
268
|
+
def speak_event
|
269
|
+
bot.command :speak do |event|
|
270
|
+
@evnt = event
|
271
|
+
@message = event.message.content.split(" ")[1..].join(" ")
|
272
|
+
@user = User.find_by(discord_id: event.user.id)
|
273
|
+
@chat = Chat.where(id: user.current_chat_id).last
|
274
|
+
event.respond error_messages[:user_not_logged_in] if user.nil?
|
275
|
+
event.respond error_messages[:user_not_in_voice_channel] if event.user.voice_channel.nil? && user
|
276
|
+
event.respond error_messages[:bot_not_in_voice_channel] if !event.voice && user
|
277
|
+
event.respond error_messages[:chat_not_found] if user && event.user.voice_channel && event.voice && chat.nil?
|
278
|
+
ask_to_speak_action if user && event.user.voice_channel && event.voice && !chat.nil?
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def ask_to_speak_action
|
283
|
+
Message.create(chat_id: chat.id, content: message, role: "user")
|
284
|
+
response = chatter.chat(message, chat.id)
|
285
|
+
audio_path = audio_synthesis.synthesize_text(response)
|
286
|
+
speak_answer_action(audio_path, response)
|
287
|
+
end
|
288
|
+
|
289
|
+
def speak_answer_action(audio_path, response)
|
290
|
+
evnt.respond response
|
291
|
+
evnt.voice.play_file(audio_path)
|
292
|
+
delete_all_voice_files
|
293
|
+
"OK"
|
294
|
+
end
|
295
|
+
|
296
|
+
def bot_init
|
297
|
+
logger.log("Discord bot started")
|
298
|
+
at_exit { bot.stop }
|
299
|
+
bot.run
|
300
|
+
rescue StandardError
|
301
|
+
start
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|