chatgpt_assistant 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env_prod_sample +18 -0
- data/.env_sample +1 -1
- data/.workflow_secrets_sample +6 -0
- data/Gemfile +5 -3
- data/Gemfile.lock +6 -0
- data/README.md +80 -8
- data/docker-compose.prod.yml +2 -2
- data/exe/chatgpt_assistant +10 -0
- data/lib/bots/application_bot.rb +3 -4
- data/lib/bots/discord_bot.rb +57 -67
- data/lib/bots/telegram_bot.rb +74 -76
- data/lib/chatgpt_assistant/audio_recognition.rb +17 -12
- data/lib/chatgpt_assistant/audio_synthesis.rb +1 -6
- data/lib/chatgpt_assistant/chatter.rb +2 -23
- data/lib/chatgpt_assistant/default_messages.rb +6 -2
- data/lib/chatgpt_assistant/models.rb +8 -0
- data/lib/chatgpt_assistant/version.rb +1 -1
- data/lib/chatgpt_assistant.rb +0 -1
- metadata +8 -6
- data/lib/chatgpt_assistant/chatter_logger.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c2a41c81a5e742715d9b0710ff7c5866ba40d718931c3a6f0caa470613b23cd
|
4
|
+
data.tar.gz: 73d6d84ccabd93c017b776083689f799f78e7b81355f02ca33a552fba601cf89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e55c21e292cc6bb2ee86bf86dca5ed881a02e834e30b5bf982f028dd0e34cf23c6c1978274873a04c50a845f157034cc1132050104d13899dce97d3c62e808cd
|
7
|
+
data.tar.gz: ca83c1370beed7b168375ed3f8ecfd168950d0fde50c72a12784e2c28a58660c5838de0c969528bd8a47ddca11b1bc6a121c825f370a20165a09dda5fec0d59e
|
data/.env_prod_sample
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
ENV_TYPE=production
|
2
|
+
LANGUAGE=en # or pt currently
|
3
|
+
MODE=aws # or ibm
|
4
|
+
DISCORD_PREFIX=gpt!
|
5
|
+
|
6
|
+
POSTGRES_DB=telegram_chatgpt_development # or your database
|
7
|
+
POSTGRES_USER=postgres # or your user
|
8
|
+
POSTGRES_PASSWORD=postgres # or your password
|
9
|
+
|
10
|
+
IBM_API_KEY=Your IBM API Key
|
11
|
+
IBM_URL=Your IBM Text to Speech URL
|
12
|
+
TELEGRAM_TOKEN=Your Telegram Bot Token
|
13
|
+
OPENAI_API_KEY=Your OpenAI API Key
|
14
|
+
AWS_ACCESS_KEY=Your AWS Access Key
|
15
|
+
AWS_SECRET_ACCESS_KEY=Your AWS Secret Access Key
|
16
|
+
AWS_REGION=Your AWS Region
|
17
|
+
DISCORD_CLIENT_ID=Your Discord Client ID
|
18
|
+
DISCORD_TOKEN=Your Discord Token
|
data/.env_sample
CHANGED
data/Gemfile
CHANGED
@@ -6,14 +6,16 @@ gem "bcrypt"
|
|
6
6
|
|
7
7
|
gem "rake", "~> 13.0"
|
8
8
|
|
9
|
-
gem "rspec", "~> 3.0"
|
9
|
+
gem "rspec", "~> 3.0", group: :test
|
10
|
+
|
11
|
+
gem "simplecov", "~> 0.21", group: :test
|
12
|
+
|
13
|
+
gem "vcr", "~> 6.0", group: :test
|
10
14
|
|
11
15
|
gem "rubocop", "~> 1.21"
|
12
16
|
|
13
17
|
gem "rubocop-rspec", "~> 2.4"
|
14
18
|
|
15
|
-
gem "simplecov", "~> 0.21"
|
16
|
-
|
17
19
|
gem "telegram-bot-ruby", "~> 0.16"
|
18
20
|
|
19
21
|
gem "discordrb", "~> 3.4"
|
data/Gemfile.lock
CHANGED
@@ -145,6 +145,7 @@ GEM
|
|
145
145
|
mime-types-data (~> 3.2015)
|
146
146
|
mime-types-data (3.2023.0218.1)
|
147
147
|
mini_mime (1.1.2)
|
148
|
+
mini_portile2 (2.8.1)
|
148
149
|
minitest (5.18.0)
|
149
150
|
multi_json (1.15.0)
|
150
151
|
multipart-post (2.3.0)
|
@@ -158,6 +159,9 @@ GEM
|
|
158
159
|
net-smtp (0.3.3)
|
159
160
|
net-protocol
|
160
161
|
netrc (0.11.0)
|
162
|
+
nokogiri (1.14.2)
|
163
|
+
mini_portile2 (~> 2.8.0)
|
164
|
+
racc (~> 1.4)
|
161
165
|
nokogiri (1.14.2-x86_64-linux)
|
162
166
|
racc (~> 1.4)
|
163
167
|
opus-ruby (1.0.1)
|
@@ -255,6 +259,7 @@ GEM
|
|
255
259
|
unf_ext
|
256
260
|
unf_ext (0.0.8.2)
|
257
261
|
unicode-display_width (2.4.2)
|
262
|
+
vcr (6.1.0)
|
258
263
|
virtus (2.0.0)
|
259
264
|
axiom-types (~> 0.1)
|
260
265
|
coercible (~> 1.0)
|
@@ -294,6 +299,7 @@ DEPENDENCIES
|
|
294
299
|
simplecov (~> 0.21)
|
295
300
|
streamio-ffmpeg
|
296
301
|
telegram-bot-ruby (~> 0.16)
|
302
|
+
vcr (~> 6.0)
|
297
303
|
|
298
304
|
BUNDLED WITH
|
299
305
|
2.2.32
|
data/README.md
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
# ChatGPT Assistant
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/chatgpt_assistant.svg)](https://badge.fury.io/rb/chatgpt_assistant)
|
4
|
+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
5
|
+
[![Ruby Version](https://img.shields.io/badge/Ruby-2.6.0%2B-blue.svg)](https://www.ruby-lang.org/en/)
|
6
|
+
|
3
7
|
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
8
|
|
9
|
+
#### Languages supported currently: en, pt - contributions are welcome!
|
10
|
+
You can contribute by adding your language to the DefaultMessages class in lib/chatgpt_assistant/default_messages.rb. You can also add your language to the list of languages in the README.md file.
|
11
|
+
Pull request from language/YOUR_LANGUAGE to main, remember to name your pull request as "Add YOUR_LANGUAGE support".
|
12
|
+
|
13
|
+
Other contributions are welcome too!
|
14
|
+
Remember to give a star to this repo if you like it!
|
5
15
|
## Requirements
|
6
16
|
|
7
17
|
- Ruby > 2.6.0
|
8
18
|
- Docker
|
9
19
|
- Docker Compose
|
20
|
+
- PostgreSQL
|
21
|
+
- Telegram Bot API Token
|
22
|
+
- Discord Bot API Token
|
23
|
+
- IBM Cloud Text to Speech API Key or AWS Polly API Key
|
24
|
+
- OpenAI API Key
|
10
25
|
|
11
26
|
## Installation
|
12
27
|
|
@@ -16,13 +31,9 @@ To install the gem, run:
|
|
16
31
|
gem install chatgpt_assistant
|
17
32
|
```
|
18
33
|
|
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
34
|
Alternatively, you can clone/fork this repo to use it as you wish.
|
24
35
|
|
25
|
-
|
36
|
+
## Installation as a gem example
|
26
37
|
|
27
38
|
```bash
|
28
39
|
gem install chatgpt_assistant
|
@@ -43,31 +54,92 @@ bundle install
|
|
43
54
|
|
44
55
|
Make sure to run bundle before using the Lucy Dockerunner rake tasks.
|
45
56
|
|
57
|
+
Then, edit the .env_sample file to include the necessary credentials and rename it to .env. Run bundle install to install the necessary dependencies.
|
58
|
+
|
59
|
+
Remember to edit docker-compose.prod.yml when deploying to production.
|
60
|
+
|
61
|
+
## Migrate your database
|
62
|
+
```bash
|
63
|
+
rake compose:up && sudo docker compose run --rm telegram exe/chatgpt_bot migrate
|
64
|
+
```
|
65
|
+
|
46
66
|
## Usage
|
47
67
|
|
48
68
|
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
69
|
|
50
70
|
For example, to start the services, run:
|
51
71
|
|
52
|
-
```
|
72
|
+
```bash
|
53
73
|
rake compose:up
|
54
74
|
```
|
55
75
|
|
56
76
|
|
57
77
|
To stop the services, run:
|
58
78
|
|
59
|
-
```
|
79
|
+
```bash
|
60
80
|
rake compose:down
|
61
81
|
```
|
62
82
|
|
63
83
|
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
84
|
|
65
|
-
|
85
|
+
#### More compose rake tasks at https://github.com/JesusGautamah/lucy_dockerunner
|
86
|
+
|
87
|
+
## Discord Bot Commands
|
88
|
+
|
89
|
+
The discord commands prefix can be changed in the .env file.
|
90
|
+
The default prefix is dgpt!
|
91
|
+
|
92
|
+
- dgpt!start - shows the welcome message
|
93
|
+
- dgpt!help - shows the help message
|
94
|
+
- dgpt!login email:password - logs in the user
|
95
|
+
- dgpt!register email:password - registers a new user
|
96
|
+
- dgpt!list - lists the user created chatbots
|
97
|
+
- dgpt!sl_chat CHAT TITLE - starts a chat with the chatbot with the given title
|
98
|
+
- dgpt!new_chat CHAT TITLE - creates a new chatbot with the given title
|
99
|
+
- dgpt!ask TEXT - sends a text to the chatbot
|
100
|
+
- dgpt!connect - connects the chat bot to the current channel
|
101
|
+
- dgpt!disconnect - disconnects the chat bot from the current channel
|
102
|
+
- dgpt!speak TEXT - sends a text to the chatbot and gets the response in voice
|
103
|
+
|
104
|
+
## Telegram Bot Commands
|
105
|
+
|
106
|
+
- /start - shows the welcome message
|
107
|
+
- /help - shows the help message
|
108
|
+
- login/email:password - logs in the user
|
109
|
+
- register/email:password - registers a new user
|
110
|
+
- list - lists the user created chatbots
|
111
|
+
- sl_chat/CHAT TITLE - starts a chat with the chatbot with the given title
|
112
|
+
- new_chat/CHAT TITLE - creates a new chatbot with the given title
|
113
|
+
- TEXT - sends a text to the chatbot
|
114
|
+
- VOICE_MESSAGE or AUDIO FILE - sends a voice message to the chatbot and returns the response in voice
|
115
|
+
|
116
|
+
## Recommended Actions runner
|
117
|
+
|
118
|
+
You can run Github Actions workflows locally using [act](https://github.com/nektos/act)
|
119
|
+
|
120
|
+
We recommend Act installation to run Github Actions workflows locally
|
121
|
+
as we use it to deploy the bot in a server via ssh.
|
66
122
|
|
67
123
|
## Contributing
|
68
124
|
|
125
|
+
A good way to contribute is add your language to DefaultMessages class in lib/chatgpt_assistant/default_messages.rb. You can also add your language to the list of languages in the README.md file.
|
126
|
+
|
69
127
|
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
128
|
|
129
|
+
|
130
|
+
## [![Repography logo](https://images.repography.com/logo.svg)](https://repography.com) / Recent activity [![Time period](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_badge.svg)](https://repography.com)
|
131
|
+
[![Timeline graph](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_timeline.svg)](https://github.com/JesusGautamah/chatgpt_assistant/commits)
|
132
|
+
[![Issue status graph](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_issues.svg)](https://github.com/JesusGautamah/chatgpt_assistant/issues)
|
133
|
+
|
134
|
+
[![Pull request status graph](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_prs.svg)](https://github.com/JesusGautamah/chatgpt_assistant/pulls)
|
135
|
+
[![Trending topics](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_words.svg)](https://github.com/JesusGautamah/chatgpt_assistant/commits)
|
136
|
+
|
137
|
+
[![Top contributors](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_users.svg)](https://github.com/JesusGautamah/chatgpt_assistant/graphs/contributors)
|
138
|
+
[![Activity map](https://images.repography.com/33522702/JesusGautamah/chatgpt_assistant/recent-activity/y6ZDduNWHwPzbnUFsmdGrJ99Q1vyEKGOBWFOBvzGjnM/1rZM2QrF0__3eUfUXFe6jDraYjHvypniTqDWhCequ-U_map.svg)](https://github.com/JesusGautamah/chatgpt_assistant/commits)
|
139
|
+
|
140
|
+
## Contributors
|
141
|
+
- [Jesus Gautamah](https://github.com/JesusGautamah)
|
142
|
+
|
71
143
|
## License
|
72
144
|
|
73
145
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/docker-compose.prod.yml
CHANGED
@@ -16,7 +16,7 @@ services:
|
|
16
16
|
environment:
|
17
17
|
POSTGRES_HOST: db
|
18
18
|
env_file:
|
19
|
-
- .
|
19
|
+
- .env_prod
|
20
20
|
depends_on:
|
21
21
|
- db
|
22
22
|
discord:
|
@@ -27,7 +27,7 @@ services:
|
|
27
27
|
environment:
|
28
28
|
POSTGRES_HOST: db
|
29
29
|
env_file:
|
30
|
-
- .
|
30
|
+
- .env_prod
|
31
31
|
depends_on:
|
32
32
|
- db
|
33
33
|
volumes:
|
data/exe/chatgpt_assistant
CHANGED
@@ -30,6 +30,10 @@ end
|
|
30
30
|
`cp #{gem_dir}/#{file} #{path}`
|
31
31
|
end
|
32
32
|
|
33
|
+
%w[deploy_and_build.sh deploy.sh].each do |file|
|
34
|
+
`cp #{gem_dir}/bin/#{file} #{path}`
|
35
|
+
end
|
36
|
+
|
33
37
|
%w[/.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ /db_data /db_data/*
|
34
38
|
.rspec_status .env /logs/telegram_chatgpt.log /voice/audio* /voice/ibm* /voice/polly* /voice/aws*].each do |file_to_ignore|
|
35
39
|
`echo "#{file_to_ignore}" >> #{path}/.gitignore`
|
@@ -37,7 +41,13 @@ end
|
|
37
41
|
|
38
42
|
`cd #{path} && git init`
|
39
43
|
|
44
|
+
`mkdir -p #{path}/.github/workflows`
|
45
|
+
`cp #{gem_dir}/.github/workflows/*.yml #{path}/.github/workflows`
|
46
|
+
|
40
47
|
puts "Done! Now you can run 'cd #{path} && bundle install'"
|
41
48
|
puts "Build the docker image with 'rake compose:build'"
|
42
49
|
puts "Run the bot with 'rake compose:up'"
|
43
50
|
puts "For more information, see the README.md file"
|
51
|
+
puts "We recommend Act installation to run Github Actions workflows locally"
|
52
|
+
puts "as we use it to deploy the bot in a server via ssh"
|
53
|
+
puts "https://github.com/nektos/act"
|
data/lib/bots/application_bot.rb
CHANGED
@@ -6,7 +6,6 @@ module ChatgptAssistant
|
|
6
6
|
def initialize(config)
|
7
7
|
@config = config
|
8
8
|
default_msg = DefaultMessages.new(@config.language)
|
9
|
-
@logger = ChatterLogger.new
|
10
9
|
@openai_api_key = @config.openai_api_key
|
11
10
|
@telegram_token = @config.telegram_token
|
12
11
|
@discord_token = @config.discord_token
|
@@ -32,8 +31,8 @@ module ChatgptAssistant
|
|
32
31
|
@audio_synthesis ||= AudioSynthesis.new(config)
|
33
32
|
end
|
34
33
|
|
35
|
-
def
|
36
|
-
|
34
|
+
def transcribed_text
|
35
|
+
audio_recognition.transcribe_audio(audio_url)
|
37
36
|
end
|
38
37
|
|
39
38
|
def find_useremail(email)
|
@@ -112,7 +111,7 @@ module ChatgptAssistant
|
|
112
111
|
end
|
113
112
|
|
114
113
|
attr_reader :openai_api_key, :telegram_token, :database, :default_msg,
|
115
|
-
:
|
114
|
+
:mode, :config, :discord_token, :discord_client_id,
|
116
115
|
:discord_prefix, :commom_messages, :error_messages, :success_messages,
|
117
116
|
:help_messages
|
118
117
|
end
|
data/lib/bots/discord_bot.rb
CHANGED
@@ -4,7 +4,6 @@ module ChatgptAssistant
|
|
4
4
|
# This class is responsible to handle the discord bot
|
5
5
|
class DiscordBot < ApplicationBot
|
6
6
|
def start
|
7
|
-
start_logs
|
8
7
|
start_event
|
9
8
|
login_event
|
10
9
|
register_event
|
@@ -33,23 +32,15 @@ module ChatgptAssistant
|
|
33
32
|
)
|
34
33
|
end
|
35
34
|
|
36
|
-
def start_logs
|
37
|
-
logger.log("Starting Discord bot")
|
38
|
-
logger.log("Discord Prefix: #{discord_prefix}")
|
39
|
-
end
|
40
|
-
|
41
35
|
def start_event
|
42
36
|
bot.command :start do |event|
|
43
37
|
@evnt = event
|
44
38
|
@user = event.user
|
45
39
|
start_action
|
46
40
|
end
|
47
|
-
logger.log("Start Event Configured")
|
48
41
|
end
|
49
42
|
|
50
43
|
def start_action
|
51
|
-
logger.log("USER: #{user.username} - #{user.id}\n MESSAGE: #{event.message.content}")
|
52
|
-
evnt.respond commom_messages[:start]
|
53
44
|
evnt.respond commom_messages[:start_helper].gsub("register/", "gpt!register ")
|
54
45
|
evnt.respond commom_messages[:start_sec_helper].gsub("login/", "gpt!login ")
|
55
46
|
end
|
@@ -60,7 +51,6 @@ module ChatgptAssistant
|
|
60
51
|
@evnt = event
|
61
52
|
message.nil? ? event.respond(commom_messages[:login]) : login_action
|
62
53
|
end
|
63
|
-
logger.log("Login Event Configured")
|
64
54
|
end
|
65
55
|
|
66
56
|
def login_action
|
@@ -68,13 +58,10 @@ module ChatgptAssistant
|
|
68
58
|
user_password = message.split(":")[1]
|
69
59
|
case auth_userdiscord(user_email, user_password, evnt.user.id)
|
70
60
|
when "user not found"
|
71
|
-
logger.log("User not found: #{user_email}")
|
72
61
|
evnt.respond error_messages[:user_not_found]
|
73
62
|
when "wrong password"
|
74
|
-
logger.log("Wrong password: #{user_email}")
|
75
63
|
evnt.respond error_messages[:wrong_password]
|
76
64
|
when find_useremail(user_email)
|
77
|
-
logger.log("User logged in: #{user_email}")
|
78
65
|
evnt.respond success_messages[:user_logged_in]
|
79
66
|
end
|
80
67
|
end
|
@@ -83,9 +70,8 @@ module ChatgptAssistant
|
|
83
70
|
bot.command :register do |event|
|
84
71
|
@message = event.message.content.split(" ")[1]
|
85
72
|
@evnt = event
|
86
|
-
message.nil? ? event.respond(commom_messages[:register]): register_action
|
73
|
+
message.nil? ? event.respond(commom_messages[:register]) : register_action
|
87
74
|
end
|
88
|
-
logger.log("Register Event Configured")
|
89
75
|
end
|
90
76
|
|
91
77
|
def register_action
|
@@ -95,7 +81,6 @@ module ChatgptAssistant
|
|
95
81
|
end
|
96
82
|
|
97
83
|
def create_user_action(mail, pass)
|
98
|
-
logger.log("Creating user #{mail}")
|
99
84
|
id = evnt.user.id
|
100
85
|
name = evnt.user.username
|
101
86
|
discord_user_create(id, mail, pass, name) ? evnt.respond(success_messages[:user_created]) : evnt.respond(error_messages[:user_not_created])
|
@@ -104,19 +89,15 @@ module ChatgptAssistant
|
|
104
89
|
def list_event
|
105
90
|
bot.command :list do |event|
|
106
91
|
@evnt = event
|
107
|
-
@user =
|
92
|
+
@user = find_userdiscord(event.user.id)
|
108
93
|
event.respond error_messages[:user_not_logged_in] if user.nil?
|
109
|
-
|
110
|
-
|
111
|
-
event.respond error_messages[:chat_not_found] if chats.empty? && user
|
112
|
-
|
113
|
-
list_action if user && !chats.empty?
|
94
|
+
event.respond error_messages[:chat_not_found] if user.chats.empty? && user
|
95
|
+
list_action if user && !user.chats.empty?
|
114
96
|
end
|
115
|
-
logger.log("List Event Configured")
|
116
97
|
end
|
117
98
|
|
118
99
|
def list_action
|
119
|
-
chats_title = chats.map(&:title)
|
100
|
+
chats_title = user.chats.map(&:title)
|
120
101
|
evnt.respond commom_messages[:chat_list]
|
121
102
|
evnt.respond chats_title.join("\n")
|
122
103
|
end
|
@@ -124,14 +105,13 @@ module ChatgptAssistant
|
|
124
105
|
def hist_event
|
125
106
|
bot.command :hist do |event|
|
126
107
|
@evnt = event
|
127
|
-
@user =
|
108
|
+
@user = find_userdiscord(event.user.id)
|
128
109
|
event.respond error_messages[:user_not_logged_in] if user.nil?
|
129
|
-
title = event.message.content.split(" ")[1
|
130
|
-
@chat =
|
110
|
+
title = event.message.content.split(" ")[1..].join(" ")
|
111
|
+
@chat = user.chat_by_title(title)
|
131
112
|
event.respond error_messages[:chat_not_found] if chat.nil? && user
|
132
113
|
hist_action if user && chat
|
133
114
|
end
|
134
|
-
logger.log("Hist Event Configured")
|
135
115
|
end
|
136
116
|
|
137
117
|
def hist_action
|
@@ -144,34 +124,32 @@ module ChatgptAssistant
|
|
144
124
|
|
145
125
|
def help_event
|
146
126
|
bot.command :help do |event|
|
147
|
-
@evnt
|
127
|
+
@evnt = event
|
148
128
|
help_action
|
149
129
|
end
|
150
|
-
logger.log("Help Event Configured")
|
151
130
|
end
|
152
131
|
|
153
132
|
def help_action
|
154
|
-
message = help_messages.join("\n").gsub(" /",
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
133
|
+
message = help_messages.join("\n").gsub(" /", discord_prefix)
|
134
|
+
.gsub("register/", "#{discord_prefix}register ")
|
135
|
+
.gsub("login/", "#{discord_prefix}login ")
|
136
|
+
.gsub("new_chat/", "#{discord_prefix}new_chat/")
|
137
|
+
.gsub("sl_chat/", "#{discord_prefix}sl_chat/")
|
159
138
|
evnt.respond message
|
160
139
|
end
|
161
140
|
|
162
141
|
def new_chat_event
|
163
142
|
bot.command :new_chat do |event|
|
164
143
|
@evnt = event
|
165
|
-
@user =
|
144
|
+
@user = find_userdiscord(event.user.id)
|
166
145
|
event.respond error_messages[:user_not_logged_in] if user.nil?
|
167
146
|
create_chat_action if user
|
168
147
|
end
|
169
|
-
logger.log("New Chat Event Configured")
|
170
148
|
end
|
171
149
|
|
172
150
|
def create_chat_action
|
173
|
-
chat_title =
|
174
|
-
chat = Chat.new(user_id: user.id, title: chat_title, status: 0)
|
151
|
+
chat_title = evnt.message.content.split(" ")[1..].join(" ")
|
152
|
+
@chat = Chat.new(user_id: user.id, title: chat_title, status: 0)
|
175
153
|
chat.save ? respond_with_success : evnt.respond(error_messages[:chat_creation])
|
176
154
|
end
|
177
155
|
|
@@ -184,17 +162,15 @@ module ChatgptAssistant
|
|
184
162
|
bot.command :sl_chat do |event|
|
185
163
|
@evnt = event
|
186
164
|
chat_to_select = event.message.content.split(" ")[1..].join(" ")
|
187
|
-
|
188
|
-
@user = User.find_by(discord_id: event.user.id)
|
165
|
+
@user = find_userdiscord(event.user.id)
|
189
166
|
event.respond error_messages[:user_not_logged_in] if user.nil?
|
190
167
|
|
191
168
|
sl_chat_action(chat_to_select) if user
|
192
169
|
end
|
193
|
-
logger.log("SL Chat Event Configured")
|
194
170
|
end
|
195
171
|
|
196
172
|
def sl_chat_action(chat_to_select)
|
197
|
-
@chat =
|
173
|
+
@chat = user.chat_by_title(chat_to_select)
|
198
174
|
evnt.respond error_messages[:chat_not_found] if chat.nil?
|
199
175
|
user.update(current_chat_id: chat.id) if chat
|
200
176
|
evnt.respond success_messages[:chat_selected] if chat
|
@@ -204,11 +180,10 @@ module ChatgptAssistant
|
|
204
180
|
bot.command :ask do |event|
|
205
181
|
@evnt = event
|
206
182
|
@message = event.message.content.split(" ")[1..].join(" ")
|
207
|
-
@user =
|
183
|
+
@user = find_userdiscord(event.user.id)
|
208
184
|
event.respond error_messages[:user_not_logged_in] if user.nil?
|
209
185
|
ask_action if user
|
210
186
|
end
|
211
|
-
logger.log("Ask Event Configured")
|
212
187
|
end
|
213
188
|
|
214
189
|
def ask_action
|
@@ -226,16 +201,23 @@ module ChatgptAssistant
|
|
226
201
|
def voice_connect_event
|
227
202
|
bot.command :connect do |event|
|
228
203
|
@evnt = event
|
229
|
-
@user =
|
204
|
+
@user = find_userdiscord(event.user.id)
|
230
205
|
@chat = Chat.where(id: user.current_chat_id).last
|
231
|
-
|
232
|
-
|
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
|
206
|
+
voice_connect_checker_action
|
207
|
+
voice_connection_checker_action
|
235
208
|
bot.voice_connect(event.user.voice_channel) if bot_disconnected?
|
236
|
-
"Connected to voice channel"
|
209
|
+
bot_connected? ? "Connected to voice channel" : "Error connecting to voice channel"
|
237
210
|
end
|
238
|
-
|
211
|
+
end
|
212
|
+
|
213
|
+
def voice_connect_checker_action
|
214
|
+
evnt.respond error_messages[:user_not_logged_in] if user.nil?
|
215
|
+
evnt.respond error_messages[:chat_not_found] if user && chat.nil?
|
216
|
+
end
|
217
|
+
|
218
|
+
def voice_connection_checker_action
|
219
|
+
evnt.respond error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
|
220
|
+
evnt.respond error_messages[:bot_already_connected] if evnt.voice && user
|
239
221
|
end
|
240
222
|
|
241
223
|
def bot_disconnected?
|
@@ -249,19 +231,20 @@ module ChatgptAssistant
|
|
249
231
|
def disconnect_event
|
250
232
|
bot.command :disconnect do |event|
|
251
233
|
@evnt = event
|
252
|
-
@user =
|
253
|
-
|
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
|
234
|
+
@user = find_userdiscord(event.user.id)
|
235
|
+
disconnect_checker_action
|
256
236
|
disconnect_action if user && event.user.voice_channel && event.voice
|
257
237
|
end
|
258
|
-
|
238
|
+
end
|
239
|
+
|
240
|
+
def disconnect_checker_action
|
241
|
+
evnt.respond error_messages[:user_not_logged_in] if user.nil?
|
242
|
+
evnt.respond error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
|
243
|
+
evnt.respond error_messages[:user_not_connected] if !evnt.voice && user
|
259
244
|
end
|
260
245
|
|
261
246
|
def disconnect_action
|
262
|
-
|
263
|
-
bot.voice_destroy(event.user.voice_channel)
|
264
|
-
logger.log("Disconnected from voice channel: #{evnt.user.voice_channel.name}")
|
247
|
+
bot.voice_destroy(evnt.user.voice_channel)
|
265
248
|
"Disconnected from voice channel"
|
266
249
|
end
|
267
250
|
|
@@ -269,16 +252,24 @@ module ChatgptAssistant
|
|
269
252
|
bot.command :speak do |event|
|
270
253
|
@evnt = event
|
271
254
|
@message = event.message.content.split(" ")[1..].join(" ")
|
272
|
-
@user =
|
273
|
-
@chat =
|
274
|
-
|
275
|
-
|
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?
|
255
|
+
@user = find_userdiscord(event.user.id)
|
256
|
+
@chat = user.current_chat
|
257
|
+
speak_connect_checker_action
|
258
|
+
speak_connection_checker_action
|
278
259
|
ask_to_speak_action if user && event.user.voice_channel && event.voice && !chat.nil?
|
279
260
|
end
|
280
261
|
end
|
281
262
|
|
263
|
+
def speak_connect_checker_action
|
264
|
+
evnt.respond error_messages[:user_not_logged_in] if user.nil?
|
265
|
+
evnt.respond error_messages[:chat_not_found] if user && evnt.user.voice_channel && evnt.voice && chat.nil?
|
266
|
+
end
|
267
|
+
|
268
|
+
def speak_connection_checker_action
|
269
|
+
evnt.respond error_messages[:user_not_in_voice_channel] if evnt.user.voice_channel.nil? && user
|
270
|
+
evnt.respond error_messages[:bot_not_in_voice_channel] if !evnt.voice && user
|
271
|
+
end
|
272
|
+
|
282
273
|
def ask_to_speak_action
|
283
274
|
Message.create(chat_id: chat.id, content: message, role: "user")
|
284
275
|
response = chatter.chat(message, chat.id)
|
@@ -294,7 +285,6 @@ module ChatgptAssistant
|
|
294
285
|
end
|
295
286
|
|
296
287
|
def bot_init
|
297
|
-
logger.log("Discord bot started")
|
298
288
|
at_exit { bot.stop }
|
299
289
|
bot.run
|
300
290
|
rescue StandardError
|
data/lib/bots/telegram_bot.rb
CHANGED
@@ -4,59 +4,72 @@ module ChatgptAssistant
|
|
4
4
|
# This class is responsible for the telegram bot features
|
5
5
|
class TelegramBot < ApplicationBot
|
6
6
|
def start
|
7
|
-
start_log
|
8
7
|
bot.listen do |message|
|
9
8
|
@msg = message
|
10
|
-
|
11
|
-
|
12
|
-
message_received_log
|
13
|
-
message_text_cases if msg.text.present?
|
14
|
-
message_audio_process if msg.audio.present? || msg.voice.present?
|
9
|
+
event_callback
|
15
10
|
end
|
11
|
+
rescue StandardError
|
12
|
+
retry
|
16
13
|
end
|
17
14
|
|
18
15
|
private
|
19
16
|
|
20
17
|
attr_accessor :msg
|
21
18
|
|
22
|
-
def
|
23
|
-
|
19
|
+
def event_callback
|
20
|
+
return unless text_or_audio?
|
21
|
+
|
22
|
+
text_events if msg.text.present?
|
23
|
+
audio_event if msg.audio.present? || msg.voice.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def text_events
|
24
27
|
case msg.text
|
25
28
|
when "/start"
|
26
|
-
|
29
|
+
start_event
|
27
30
|
when "/help"
|
28
|
-
|
31
|
+
help_event
|
29
32
|
when "/list"
|
30
|
-
|
33
|
+
list_event
|
31
34
|
when "/stop"
|
32
|
-
|
35
|
+
stop_event
|
33
36
|
when "/hist"
|
34
|
-
|
37
|
+
hist_event
|
35
38
|
when nil
|
36
|
-
|
39
|
+
nil_event
|
37
40
|
else
|
38
|
-
|
41
|
+
action_events
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
chat =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
def audio_event
|
46
|
+
return bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:no_chat_selected]) if user.current_chat.nil?
|
47
|
+
|
48
|
+
chat = user.current_chat
|
49
|
+
user_audio = transcribed_file
|
50
|
+
message = Message.new(content: user_audio["text"], chat_id: chat.id, role: "user")
|
51
|
+
if message.save
|
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])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def send_audio_message(voice, text)
|
50
62
|
bot.api.send_voice(chat_id: msg.chat.id, voice: Faraday::UploadIO.new(voice, "audio/mp3"))
|
51
|
-
|
63
|
+
bot.api.send_message(chat_id: msg.chat.id, text: text)
|
52
64
|
end
|
53
65
|
|
54
|
-
def
|
66
|
+
def action_events
|
55
67
|
return chatter_call unless actions?
|
56
68
|
return new_chat if msg.text.include?("new_chat/")
|
57
69
|
return select_chat if msg.text.include?("sl_chat/")
|
58
70
|
return login if msg.text.include?("login/")
|
59
71
|
return register if msg.text.include?("register/")
|
72
|
+
|
60
73
|
invalid_command_error_message
|
61
74
|
end
|
62
75
|
|
@@ -68,7 +81,7 @@ module ChatgptAssistant
|
|
68
81
|
user_not_found_error_message
|
69
82
|
when "wrong password"
|
70
83
|
wrong_password_error_message
|
71
|
-
when
|
84
|
+
when find_useremail(email)
|
72
85
|
user_logged_in_message
|
73
86
|
end
|
74
87
|
end
|
@@ -95,11 +108,11 @@ module ChatgptAssistant
|
|
95
108
|
"https://api.telegram.org/file/bot#{telegram_token}/#{audio_info["result"]["file_path"]}"
|
96
109
|
end
|
97
110
|
|
98
|
-
def
|
111
|
+
def transcribed_file
|
99
112
|
audio_recognition.transcribe_audio(audio_url)
|
100
113
|
end
|
101
114
|
|
102
|
-
def
|
115
|
+
def start_event
|
103
116
|
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:start])
|
104
117
|
help_message = help_messages.join("\n").to_s
|
105
118
|
bot.api.send_message(chat_id: msg.chat.id, text: help_message)
|
@@ -107,38 +120,30 @@ module ChatgptAssistant
|
|
107
120
|
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:start_sec_helper])
|
108
121
|
end
|
109
122
|
|
110
|
-
def
|
123
|
+
def hist_event
|
111
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
|
112
126
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
return bot.api.send_message(chat_id: msg.chat.id,
|
117
|
-
text: error_messages[:no_messages_founded])
|
118
|
-
end
|
119
|
-
|
120
|
-
response = chat.messages.last(4).map do |mess|
|
121
|
-
"#{mess.role}: #{mess.content}\n at: #{mess.created_at}\n\n"
|
122
|
-
end.join
|
123
|
-
logger.log("HIST RESPONSE: #{response}")
|
124
|
-
bot.api.send_message(chat_id: msg.chat.id, text: response)
|
125
|
-
else
|
126
|
-
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:no_chat_selected])
|
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])
|
127
130
|
end
|
131
|
+
|
132
|
+
response = chat.messages.last(4).map do |mess|
|
133
|
+
"#{mess.role}: #{mess.content}\n at: #{mess.created_at}\n\n"
|
134
|
+
end.join
|
135
|
+
bot.api.send_message(chat_id: msg.chat.id, text: response)
|
128
136
|
end
|
129
137
|
|
130
138
|
def select_chat
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
chat_not_found_message
|
140
|
-
end
|
141
|
-
end
|
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])
|
142
147
|
end
|
143
148
|
|
144
149
|
def new_chat
|
@@ -152,18 +157,23 @@ module ChatgptAssistant
|
|
152
157
|
chat.save ? chat_created_message(chat) : chat_creation_failed_message
|
153
158
|
end
|
154
159
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
bot.api.send_message(chat_id: msg.chat.id,
|
159
|
-
text: commom_messages[:chats_list])
|
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])
|
160
164
|
chats_str = ""
|
161
|
-
chats.each do |chat|
|
165
|
+
user.chats.each do |chat|
|
162
166
|
chats_str += "Chat #{chat.id} - #{chat.title}\n"
|
163
167
|
end
|
164
168
|
bot.api.send_message(chat_id: msg.chat.id, text: chats_str)
|
165
169
|
end
|
166
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
|
+
|
167
177
|
def chatter_call
|
168
178
|
user ? chat_if_exists : not_logged_in_message
|
169
179
|
end
|
@@ -178,18 +188,18 @@ module ChatgptAssistant
|
|
178
188
|
bot.api.send_message(chat_id: msg.chat.id, text: chatter.chat(msg.text, chat_id))
|
179
189
|
end
|
180
190
|
|
181
|
-
def
|
191
|
+
def help_event
|
182
192
|
help_messages.each do |message|
|
183
193
|
bot.api.send_message(chat_id: msg.chat.id, text: message)
|
184
194
|
end
|
185
195
|
end
|
186
196
|
|
187
|
-
def
|
197
|
+
def stop_event
|
188
198
|
bot.api.send_message(chat_id: msg.chat.id, text: commom_messages[:stop])
|
189
199
|
bot.api.leave_chat(chat_id: msg.chat.id)
|
190
200
|
end
|
191
201
|
|
192
|
-
def
|
202
|
+
def nil_event
|
193
203
|
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:nil])
|
194
204
|
end
|
195
205
|
|
@@ -233,31 +243,19 @@ module ChatgptAssistant
|
|
233
243
|
|
234
244
|
def no_chat_selected
|
235
245
|
bot.api.send_message(chat_id: msg.chat.id,
|
236
|
-
|
246
|
+
text: error_messages[:no_chat_selected])
|
237
247
|
end
|
238
248
|
|
239
249
|
def chat_not_found_message
|
240
250
|
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:chat_not_found])
|
241
251
|
end
|
242
252
|
|
243
|
-
def start_log
|
244
|
-
logger.log("STARTING BOT AT #{Time.now}")
|
245
|
-
logger.log("ENVIRONMENT: #{@config.env_type}")
|
246
|
-
end
|
247
|
-
|
248
253
|
def error_log(err)
|
249
254
|
if err.message.to_s.include?("Bad Request: message is too long")
|
250
255
|
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:message_history_too_long])
|
251
256
|
else
|
252
257
|
bot.api.send_message(chat_id: msg.chat.id, text: error_messages[:something_went_wrong])
|
253
|
-
bot.api.send_message(chat_id: msg.chat.id, text: "ERROR: #{err.message}\n #{err.backtrace}")
|
254
258
|
end
|
255
|
-
logger.log("ERROR: #{err.message}\n #{err.backtrace}")
|
256
|
-
end
|
257
|
-
|
258
|
-
def message_received_log
|
259
|
-
logger.log("MESSAGE RECEIVED AT: #{Time.now}")
|
260
|
-
logger.log("MESSAGE FROM USER: #{msg.from.first_name} #{msg.from.last_name} - #{msg.from.username}")
|
261
259
|
end
|
262
260
|
|
263
261
|
def user
|
@@ -4,25 +4,24 @@ module ChatgptAssistant
|
|
4
4
|
# This is the AudioRecognition class
|
5
5
|
class AudioRecognition
|
6
6
|
def initialize(openai_api_key)
|
7
|
+
time = Time.now.to_i
|
8
|
+
@dl_file_name = "voice/audio-#{time}.oga"
|
9
|
+
@file_name = "voice/audio-#{time}.mp3"
|
7
10
|
@conn = Faraday.new(url: "https://api.openai.com/") do |faraday|
|
8
11
|
faraday.request :multipart
|
9
12
|
faraday.request :url_encoded
|
10
13
|
faraday.adapter Faraday.default_adapter
|
11
14
|
end
|
12
|
-
@logger = ChatterLogger.new
|
13
15
|
@openai_api_key = openai_api_key
|
14
16
|
end
|
15
17
|
|
16
18
|
def download_audio(audio_url)
|
17
|
-
logger.log("DOWNLOADING AUDIO FROM TELEGRAM")
|
18
|
-
@time = Time.now.to_i
|
19
19
|
audio_conn = Faraday.new(url: audio_url)
|
20
|
-
File.open(
|
20
|
+
File.open(dl_file_name, "wb") do |file|
|
21
21
|
file.write(audio_conn.get.body)
|
22
22
|
end
|
23
|
-
|
24
|
-
|
25
|
-
File.delete("voice/audio-#{time}.oga")
|
23
|
+
FFMPEG::Movie.new(dl_file_name).transcode(file_name)
|
24
|
+
File.delete(dl_file_name)
|
26
25
|
end
|
27
26
|
|
28
27
|
def header
|
@@ -34,21 +33,27 @@ module ChatgptAssistant
|
|
34
33
|
|
35
34
|
def payload
|
36
35
|
{
|
37
|
-
"file": Faraday::UploadIO.new(
|
36
|
+
"file": Faraday::UploadIO.new(file_name, "audio/mp3"),
|
38
37
|
"model": "whisper-1"
|
39
38
|
}
|
40
39
|
end
|
41
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
|
+
|
42
48
|
def transcribe_audio(audio_url)
|
43
49
|
@audio_url = audio_url
|
44
50
|
download_audio(audio_url)
|
45
|
-
response = conn.post("v1/audio/transcriptions", payload, header)
|
46
|
-
|
47
|
-
JSON.parse(response.body)["text"]
|
51
|
+
@response = conn.post("v1/audio/transcriptions", payload, header)
|
52
|
+
transcribed_file_json
|
48
53
|
end
|
49
54
|
|
50
55
|
private
|
51
56
|
|
52
|
-
attr_reader :conn, :openai_api_key, :
|
57
|
+
attr_reader :conn, :openai_api_key, :audio_url, :time, :ibm_api_key, :ibm_url, :response, :dl_file_name, :file_name
|
53
58
|
end
|
54
59
|
end
|
@@ -9,7 +9,6 @@ module ChatgptAssistant
|
|
9
9
|
@openai_api_key = config.openai_api_key
|
10
10
|
@language = config.language
|
11
11
|
@conn = faraday_instance
|
12
|
-
@logger = ChatterLogger.new
|
13
12
|
classify_mode
|
14
13
|
end
|
15
14
|
|
@@ -24,7 +23,7 @@ module ChatgptAssistant
|
|
24
23
|
private
|
25
24
|
|
26
25
|
attr_reader :openai_api_key, :ibm_api_key, :ibm_url, :aws_access_key_id, :aws_secret_access_key, :aws_region,
|
27
|
-
:config, :
|
26
|
+
:config, :language, :voice
|
28
27
|
|
29
28
|
def faraday_instance
|
30
29
|
Faraday.new(url: "https://api.openai.com/") do |faraday|
|
@@ -49,7 +48,6 @@ module ChatgptAssistant
|
|
49
48
|
|
50
49
|
def synthesize_text_aws(text)
|
51
50
|
time = Time.now.to_i
|
52
|
-
logger.log("SYNTHESIZING TEXT WITH AWS POLLY")
|
53
51
|
@time = Time.now.to_i
|
54
52
|
polly_client = Aws::Polly::Client.new(
|
55
53
|
access_key_id: aws_access_key_id,
|
@@ -66,14 +64,11 @@ module ChatgptAssistant
|
|
66
64
|
File.open("voice/aws-#{time}.mp3", "wb") do |file|
|
67
65
|
file.write(response.audio_stream.read)
|
68
66
|
end
|
69
|
-
|
70
|
-
logger.log("SYNTHESIZED TEXT WITH AWS POLLY")
|
71
67
|
"voice/aws-#{time}.mp3"
|
72
68
|
end
|
73
69
|
|
74
70
|
def synthesize_text_ibm(text)
|
75
71
|
time = Time.now.to_i
|
76
|
-
logger.log("SYNTHESIZING TEXT WITH IBM WATSON")
|
77
72
|
authenticator = IBMWatson::Authenticators::IamAuthenticator.new(
|
78
73
|
apikey: ibm_api_key
|
79
74
|
)
|
@@ -2,45 +2,34 @@
|
|
2
2
|
|
3
3
|
require "faraday"
|
4
4
|
require_relative "models"
|
5
|
-
require_relative "chatter_logger"
|
6
5
|
|
7
6
|
module ChatgptAssistant
|
8
7
|
# This is the Chat Ai class
|
9
8
|
class Chatter
|
10
9
|
def initialize(openai_api_key)
|
11
10
|
@openai_api_key = openai_api_key
|
12
|
-
@logger = ChatterLogger.new
|
13
11
|
end
|
14
12
|
|
15
13
|
def chat(message, chat_id)
|
16
14
|
@chat_id = chat_id
|
17
15
|
@message = message
|
18
|
-
init_log
|
19
16
|
@response = request(message)
|
20
17
|
@json = JSON.parse(response.body)
|
21
|
-
logger.log("RESPONSE FROM OPENAI API: OK")
|
22
18
|
|
23
19
|
return error_log if response.status != 200
|
24
20
|
|
25
21
|
text = json["choices"][0]["message"]["content"]
|
26
22
|
|
27
23
|
Message.create(content: text, role: "assistant", chat_id: chat_id)
|
28
|
-
logger.log("MESSAGE SAVED IN DATABASE")
|
29
24
|
text
|
30
25
|
end
|
31
26
|
|
32
27
|
private
|
33
28
|
|
34
|
-
attr_reader :openai_api_key, :response, :message
|
29
|
+
attr_reader :openai_api_key, :response, :message
|
35
30
|
attr_accessor :chat_id, :json
|
36
31
|
|
37
|
-
def init_log
|
38
|
-
logger.log("REQUESTING OPENAI API COMPLETION")
|
39
|
-
end
|
40
|
-
|
41
32
|
def error_log
|
42
|
-
logger.log("RESPONSE FROM OPENAI API ERROR")
|
43
|
-
logger.log("RESPONSE STATUS: #{response.status}")
|
44
33
|
"Algo deu errado, tente novamente mais tarde."
|
45
34
|
end
|
46
35
|
|
@@ -60,17 +49,7 @@ module ChatgptAssistant
|
|
60
49
|
|
61
50
|
def request_params(message)
|
62
51
|
messages = Message.where(chat_id: chat_id).order(id: :asc).last(10)
|
63
|
-
|
64
|
-
ids = ["unknown"]
|
65
|
-
messages = [{ role: "user", content: message }]
|
66
|
-
else
|
67
|
-
ids = messages.map(&:id)
|
68
|
-
messages = messages.map { |mess| { role: mess.role, content: mess.content } }
|
69
|
-
end
|
70
|
-
logger.log("MESSAGES LOADED IN CONTEXT: #{messages.count}")
|
71
|
-
messages.each_with_index do |mess, index|
|
72
|
-
logger.log("MESSAGE ROLE: #{mess[:role]}, ID: #{ids[index]}")
|
73
|
-
end
|
52
|
+
messages = messages.empty? ? [{ role: "user", content: message }] : messages.map { |mess| { role: mess.role, content: mess.content } }
|
74
53
|
{
|
75
54
|
model: "gpt-3.5-turbo",
|
76
55
|
messages: messages
|
@@ -51,6 +51,7 @@ module ChatgptAssistant
|
|
51
51
|
nil: "Não entendi o que você disse. Tente novamente",
|
52
52
|
email: "O email que você digitou não é válido. Tente novamente",
|
53
53
|
password: "A senha que você digitou não é válida. Tente novamente",
|
54
|
+
wrong_password: "A senha que você digitou não é válida. Tente novamente",
|
54
55
|
user: "O usuário que você digitou não existe. Tente novamente",
|
55
56
|
user_creation: "Erro ao criar usuário. Tente novamente",
|
56
57
|
user_already_exists: "O usuário que você digitou já existe. Tente novamente",
|
@@ -66,7 +67,8 @@ module ChatgptAssistant
|
|
66
67
|
text_length: "O texto de resposta é muito longo. Tente diminuir a quantidade de respostas na mesma mensagem.",
|
67
68
|
user_not_in_voice_channel: "Você não está em um canal de voz.",
|
68
69
|
bot_not_in_voice_channel: "O bot não está em um canal de voz.",
|
69
|
-
invalid_command: "Comando inválido. Tente novamente."
|
70
|
+
invalid_command: "Comando inválido. Tente novamente.",
|
71
|
+
message_creation_error: "Erro ao criar mensagem. Tente novamente."
|
70
72
|
}
|
71
73
|
end
|
72
74
|
|
@@ -112,6 +114,7 @@ module ChatgptAssistant
|
|
112
114
|
nil: "I didn't understand what you said. Try again",
|
113
115
|
email: "The email you typed is not valid. Try again",
|
114
116
|
password: "The password you typed is not valid. Try again",
|
117
|
+
wrong_password: "The password you typed is not valid. Try again",
|
115
118
|
user: "The user you typed does not exist. Try again",
|
116
119
|
user_creation: "Error creating user. Try again",
|
117
120
|
chat_creation: "Error creating chat. Try again",
|
@@ -126,7 +129,8 @@ module ChatgptAssistant
|
|
126
129
|
text_length: "The response text is too long. Try to reduce the number of answers in the same message.",
|
127
130
|
user_not_in_voice_channel: "You are not in a voice channel.",
|
128
131
|
bot_not_in_voice_channel: "The bot is not in a voice channel.",
|
129
|
-
invalid_command: "Invalid command. Try again."
|
132
|
+
invalid_command: "Invalid command. Try again.",
|
133
|
+
message_creation_error: "Error creating message. Try again."
|
130
134
|
}
|
131
135
|
end
|
132
136
|
|
@@ -21,9 +21,17 @@ class User < ActiveRecord::Base
|
|
21
21
|
self.password_hash = BCrypt::Engine.hash_secret(password_hash, password_salt)
|
22
22
|
end
|
23
23
|
|
24
|
+
def current_chat
|
25
|
+
chats.find(current_chat_id)
|
26
|
+
end
|
27
|
+
|
24
28
|
def last_chat
|
25
29
|
chats.last
|
26
30
|
end
|
31
|
+
|
32
|
+
def chat_by_title(title)
|
33
|
+
chats.find_by(title: title)
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
37
|
# Chat model
|
data/lib/chatgpt_assistant.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require_relative "chatgpt_assistant/audio_recognition"
|
4
4
|
require_relative "chatgpt_assistant/default_messages"
|
5
5
|
require_relative "chatgpt_assistant/audio_synthesis"
|
6
|
-
require_relative "chatgpt_assistant/chatter_logger"
|
7
6
|
require_relative "chatgpt_assistant/chatter"
|
8
7
|
require_relative "chatgpt_assistant/version"
|
9
8
|
require_relative "chatgpt_assistant/config"
|
metadata
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chatgpt_assistant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JesusGautamah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
This gem has the intention to facilitate the creation of chatbots with GPT-3.5-turbo,
|
15
|
-
Telegram bot, Discord bot, Audio Transcription and IBM Cloud Text to Speech in docker containers.
|
15
|
+
Telegram bot, Discord bot, Audio Transcription and IBM Cloud Text to Speech or AWS Polly in docker containers.
|
16
|
+
Documentation: https://github.com/JesusGautamah/chatgpt_assistant
|
16
17
|
email:
|
17
18
|
- lima.jesuscc@gmail.com
|
18
19
|
executables:
|
@@ -21,9 +22,11 @@ executables:
|
|
21
22
|
extensions: []
|
22
23
|
extra_rdoc_files: []
|
23
24
|
files:
|
25
|
+
- ".env_prod_sample"
|
24
26
|
- ".env_sample"
|
25
27
|
- ".rspec"
|
26
28
|
- ".rubocop.yml"
|
29
|
+
- ".workflow_secrets_sample"
|
27
30
|
- CHANGELOG.md
|
28
31
|
- CODE_OF_CONDUCT.md
|
29
32
|
- CONTRIBUTING.md
|
@@ -47,7 +50,6 @@ files:
|
|
47
50
|
- lib/chatgpt_assistant/audio_recognition.rb
|
48
51
|
- lib/chatgpt_assistant/audio_synthesis.rb
|
49
52
|
- lib/chatgpt_assistant/chatter.rb
|
50
|
-
- lib/chatgpt_assistant/chatter_logger.rb
|
51
53
|
- lib/chatgpt_assistant/config.rb
|
52
54
|
- lib/chatgpt_assistant/default_messages.rb
|
53
55
|
- lib/chatgpt_assistant/migrations.rb
|
@@ -63,7 +65,7 @@ metadata:
|
|
63
65
|
allowed_push_host: https://rubygems.org
|
64
66
|
homepage_uri: https://github.com/JesusGautamah/chatgpt_assistant
|
65
67
|
source_code_uri: https://github.com/JesusGautamah/chatgpt_assistant.git
|
66
|
-
changelog_uri: https://github.com/JesusGautamah/chatgpt_assistant/
|
68
|
+
changelog_uri: https://github.com/JesusGautamah/chatgpt_assistant/releases
|
67
69
|
post_install_message:
|
68
70
|
rdoc_options: []
|
69
71
|
require_paths:
|
@@ -83,5 +85,5 @@ rubygems_version: 3.2.32
|
|
83
85
|
signing_key:
|
84
86
|
specification_version: 4
|
85
87
|
summary: Easy way chatbot with GPT-3.5-turbo, Telegram bot, Discord bot, Audio Transcription
|
86
|
-
and IBM Cloud Text to Speech.
|
88
|
+
and IBM Cloud Text to Speech or AWS Polly in docker containers.
|
87
89
|
test_files: []
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ChatgptAssistant
|
4
|
-
# This class is responsible for logging the messages
|
5
|
-
class ChatterLogger
|
6
|
-
def initialize
|
7
|
-
@file_name = "logs/telegram_chatgpt.log"
|
8
|
-
@log_file = File.open("logs/telegram_chatgpt.log", "a")
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_reader :log_file
|
12
|
-
|
13
|
-
def log(message)
|
14
|
-
log_file.puts(message)
|
15
|
-
system "echo '#{message}'"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|