rubydium 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +28 -19
- data/example/example_bot.rb +14 -8
- data/example/open_ai_bot/Gemfile +9 -0
- data/example/open_ai_bot/chat_gpt.rb +111 -0
- data/example/open_ai_bot/chat_thread.rb +57 -0
- data/example/open_ai_bot/dalle.rb +22 -0
- data/example/open_ai_bot/open_ai_bot.rb +68 -0
- data/example/open_ai_bot/utils.rb +25 -0
- data/example/open_ai_bot/whisper.rb +45 -0
- data/lib/rubydium/mixins/message_sending.rb +7 -0
- data/lib/rubydium/version.rb +1 -1
- data/rubydium.gemspec +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebfa6d1d46ec5b5d046aae44b857f59b405e5ae79af529d695a552090dc07fc0
|
4
|
+
data.tar.gz: 00cd4177e06fb2920a5ff6a1b8c3be332bc57cbf473624020704855df07dec07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f09704c30374104c0c0cf608ffae1ffad372e2b41317f9a324a6ae1200867393d461fe186ec2f62c5516c38c293ba812ef1016ccf8cab3342a655ca702390358
|
7
|
+
data.tar.gz: 478056c327c16135dd0a546fc88c53dd345ca5db7b30047b673c6765c0f22d07a54f8b877eae86a18dceef5b4de5c55db6ecb9a7a10fa65df05f4956e18c1c4e
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,20 +6,33 @@ GEM
|
|
6
6
|
console (~> 1.10)
|
7
7
|
io-event (~> 1.1)
|
8
8
|
timers (~> 4.1)
|
9
|
-
|
10
|
-
descendants_tracker (~> 0.0.4)
|
11
|
-
ice_nine (~> 0.11.0)
|
12
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
9
|
+
base64 (0.1.1)
|
13
10
|
coderay (1.1.3)
|
14
|
-
|
15
|
-
descendants_tracker (~> 0.0.1)
|
11
|
+
concurrent-ruby (1.2.2)
|
16
12
|
console (1.16.2)
|
17
13
|
fiber-local
|
18
|
-
descendants_tracker (0.0.4)
|
19
|
-
thread_safe (~> 0.3, >= 0.3.1)
|
20
14
|
diff-lcs (1.5.0)
|
15
|
+
dry-core (1.0.1)
|
16
|
+
concurrent-ruby (~> 1.0)
|
17
|
+
zeitwerk (~> 2.6)
|
21
18
|
dry-inflector (1.0.0)
|
22
|
-
|
19
|
+
dry-logic (1.5.0)
|
20
|
+
concurrent-ruby (~> 1.0)
|
21
|
+
dry-core (~> 1.0, < 2)
|
22
|
+
zeitwerk (~> 2.6)
|
23
|
+
dry-struct (1.6.0)
|
24
|
+
dry-core (~> 1.0, < 2)
|
25
|
+
dry-types (>= 1.7, < 2)
|
26
|
+
ice_nine (~> 0.11)
|
27
|
+
zeitwerk (~> 2.6)
|
28
|
+
dry-types (1.7.1)
|
29
|
+
concurrent-ruby (~> 1.0)
|
30
|
+
dry-core (~> 1.0)
|
31
|
+
dry-inflector (~> 1.0)
|
32
|
+
dry-logic (~> 1.4)
|
33
|
+
zeitwerk (~> 2.6)
|
34
|
+
faraday (2.7.11)
|
35
|
+
base64
|
23
36
|
faraday-net_http (>= 2.0, < 3.1)
|
24
37
|
ruby2_keywords (>= 0.0.4)
|
25
38
|
faraday-multipart (1.0.4)
|
@@ -30,7 +43,7 @@ GEM
|
|
30
43
|
io-event (1.1.5)
|
31
44
|
json (2.6.3)
|
32
45
|
method_source (1.0.0)
|
33
|
-
multipart-post (2.
|
46
|
+
multipart-post (2.3.0)
|
34
47
|
parallel (1.22.1)
|
35
48
|
parser (3.1.3.0)
|
36
49
|
ast (~> 2.4.1)
|
@@ -69,18 +82,14 @@ GEM
|
|
69
82
|
rubocop (~> 1.33)
|
70
83
|
ruby-progressbar (1.11.0)
|
71
84
|
ruby2_keywords (0.0.5)
|
72
|
-
telegram-bot-ruby (0.
|
73
|
-
dry-
|
85
|
+
telegram-bot-ruby (1.0.0)
|
86
|
+
dry-struct (~> 1.6)
|
74
87
|
faraday (~> 2.0)
|
75
88
|
faraday-multipart (~> 1.0)
|
76
|
-
|
77
|
-
thread_safe (0.3.6)
|
89
|
+
zeitwerk (~> 2.6)
|
78
90
|
timers (4.3.5)
|
79
91
|
unicode-display_width (2.3.0)
|
80
|
-
|
81
|
-
axiom-types (~> 0.1)
|
82
|
-
coercible (~> 1.0)
|
83
|
-
descendants_tracker (~> 0.0, >= 0.0.3)
|
92
|
+
zeitwerk (2.6.11)
|
84
93
|
|
85
94
|
PLATFORMS
|
86
95
|
x86_64-linux
|
@@ -91,7 +100,7 @@ DEPENDENCIES
|
|
91
100
|
rspec
|
92
101
|
rubocop
|
93
102
|
rubocop-rspec
|
94
|
-
telegram-bot-ruby
|
103
|
+
telegram-bot-ruby (~> 1.0.0)
|
95
104
|
|
96
105
|
BUNDLED WITH
|
97
106
|
2.3.26
|
data/example/example_bot.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "rubydium"
|
3
|
+
# require "rubydium"
|
4
|
+
require_relative "../lib/rubydium"
|
5
|
+
require "pry"
|
4
6
|
|
5
7
|
# Your actual logic of handling the updates goes here.
|
6
8
|
class ExampleBot < Rubydium::Bot
|
7
9
|
on_every_message :log_message
|
8
10
|
|
9
11
|
on_command "/help", description: "Show help message" do
|
10
|
-
text = help_message
|
12
|
+
text = self.class.help_message
|
11
13
|
send_message(text)
|
12
14
|
end
|
13
15
|
|
14
16
|
on_command "/start", :greet_user, description: "Say hello"
|
17
|
+
on_command "/pry" do
|
18
|
+
binding.pry
|
19
|
+
end
|
15
20
|
|
16
21
|
def log_message
|
17
22
|
puts "Got message from #{@user.first_name}, text: \n#{@text}"
|
@@ -24,12 +29,13 @@ class ExampleBot < Rubydium::Bot
|
|
24
29
|
end
|
25
30
|
|
26
31
|
ExampleBot.configure do |config|
|
27
|
-
config.token = "1234567890:long_alphanumeric_string_goes_here"
|
28
|
-
config.bot_username = "ends_with_bot"
|
29
|
-
config.owner_username = "thats_you"
|
30
|
-
config.privileged_usernames =
|
31
|
-
|
32
|
-
|
32
|
+
config.token = "1043894792:AAGC_oA2Ztvo5bBZBPxX5_oUxFX-L_obZJI"#"1234567890:long_alphanumeric_string_goes_here"
|
33
|
+
config.bot_username = "bulgakkebot"#"ends_with_bot"
|
34
|
+
config.owner_username = "bulgakke"#"thats_you"
|
35
|
+
config.privileged_usernames = []
|
36
|
+
# %w[
|
37
|
+
# your_friend your_chat_moderator
|
38
|
+
# ]
|
33
39
|
end
|
34
40
|
|
35
41
|
ExampleBot.run
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "chat_thread"
|
4
|
+
|
5
|
+
module ChatGPT
|
6
|
+
module ClassMethods
|
7
|
+
def threads
|
8
|
+
@threads ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_thread(chat_id)
|
12
|
+
new_thread = ChatThread.new(chat_id)
|
13
|
+
threads[chat_id] = new_thread
|
14
|
+
new_thread
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
base.extend ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_session
|
23
|
+
self.class.new_thread(@chat.id)
|
24
|
+
reply("Bot's context reset.")
|
25
|
+
end
|
26
|
+
|
27
|
+
def allowed_chat?
|
28
|
+
return true if @user.username == config.owner_username
|
29
|
+
return true if config.chat_gpt_allow_all_private_chats && @chat.id.positive?
|
30
|
+
return true if config.chat_gpt_allow_all_group_chats && @chat.id.negative?
|
31
|
+
return true if config.chat_gpt_whitelist.include?(@chat.id)
|
32
|
+
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_gpt_command
|
37
|
+
return if self.class.registered_commands.keys.any? { @text.match? Regexp.new(_1) }
|
38
|
+
return unless bot_mentioned? || bot_replied_to? || private_chat?
|
39
|
+
|
40
|
+
if !allowed_chat?
|
41
|
+
msg = "This chat (`#{@chat.id}`) is not whitelisted for ChatGPT usage. Ask @#{config.owner_username}."
|
42
|
+
return reply(msg, parse_mode: "Markdown")
|
43
|
+
end
|
44
|
+
|
45
|
+
text = @text_without_bot_mentions
|
46
|
+
text = nil if text.gsub(/\s/, "").empty?
|
47
|
+
|
48
|
+
target_text = @replies_to&.text || @replies_to&.caption
|
49
|
+
target_text = nil if @target&.username == config.bot_username
|
50
|
+
|
51
|
+
thread = self.class.threads[@chat.id] || self.class.new_thread(@chat.id)
|
52
|
+
|
53
|
+
name = "@#{@user.username}"
|
54
|
+
|
55
|
+
if target_text && bot_mentioned?
|
56
|
+
target_name = "@#{@replies_to.from.username}"
|
57
|
+
text = [add_name(target_name, target_text), add_name(name, text)].join("\n\n")
|
58
|
+
ask_gpt(name, text, thread)
|
59
|
+
elsif text
|
60
|
+
text = add_name(name, text)
|
61
|
+
ask_gpt(name, text, thread)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def ask_gpt(_name, prompt, thread)
|
66
|
+
thread.add!(:user, prompt)
|
67
|
+
|
68
|
+
send_request(thread)
|
69
|
+
end
|
70
|
+
|
71
|
+
def send_request(thread)
|
72
|
+
Async do |task|
|
73
|
+
request = Async do
|
74
|
+
attempt(3) do
|
75
|
+
response = open_ai.chat(
|
76
|
+
parameters: {
|
77
|
+
model: "gpt-3.5-turbo",
|
78
|
+
messages: thread.history
|
79
|
+
}
|
80
|
+
)
|
81
|
+
|
82
|
+
if response["error"]
|
83
|
+
error_text = response["error"]["message"]
|
84
|
+
error_text += "\n\nHint: press /start to reset the context." if error_text.match? "tokens"
|
85
|
+
raise Net::ReadTimeout, response["error"]["message"]
|
86
|
+
else
|
87
|
+
text = response.dig("choices", 0, "message", "content")
|
88
|
+
puts "#{Time.now.to_i} | Chat ID: #{@chat.id}, tokens used: #{response.dig("usage", "total_tokens")}"
|
89
|
+
|
90
|
+
reply(text)
|
91
|
+
thread.add!(:assistant, text)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
status = task.async do
|
97
|
+
loop do
|
98
|
+
send_chat_action(:typing)
|
99
|
+
sleep 4.5
|
100
|
+
end
|
101
|
+
end
|
102
|
+
request.wait
|
103
|
+
|
104
|
+
status.stop
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_name(name, text)
|
109
|
+
"<#{name}>:\n#{text}"
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ChatThread
|
4
|
+
def initialize(_chat)
|
5
|
+
@history = [
|
6
|
+
{
|
7
|
+
role: :system,
|
8
|
+
content: default_instruction
|
9
|
+
},
|
10
|
+
{
|
11
|
+
role: :user,
|
12
|
+
content: first_user_message
|
13
|
+
},
|
14
|
+
{
|
15
|
+
role: :assistant,
|
16
|
+
content: first_bot_message
|
17
|
+
}
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :history
|
22
|
+
|
23
|
+
def add!(role, content)
|
24
|
+
return if [role, content].any? { [nil, ""].include?(_1) }
|
25
|
+
|
26
|
+
@history.push({
|
27
|
+
role: role, content: content.gsub(/\\xD\d/, "")
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_instruction
|
32
|
+
<<~MSG
|
33
|
+
Ты находишься в групповом чате. Здесь могут использоваться разные языки, так что отвечай на вопросы на том языке, на котором они заданы.
|
34
|
+
|
35
|
+
Помимо текста сообщений, первой строчкой ты будешь получать имя пользователя, который отправил это сообщение.
|
36
|
+
Пользователи могут просить обращаться к ним иначе, чем подписано сообщение.
|
37
|
+
|
38
|
+
Тебе не нужно подписывать свои сообщения и без необходимости вставлять имена других пользователей.
|
39
|
+
|
40
|
+
Если не до конца понимаешь, о чём вопрос - задавай уточняющий вопрос в ответ. Также изредка задавай общие вопросы для продвижения диалога.
|
41
|
+
MSG
|
42
|
+
end
|
43
|
+
|
44
|
+
def first_user_message
|
45
|
+
<<~MSG
|
46
|
+
<@tyradee>:
|
47
|
+
|
48
|
+
I drank some tea today.
|
49
|
+
MSG
|
50
|
+
end
|
51
|
+
|
52
|
+
def first_bot_message
|
53
|
+
<<~MSG
|
54
|
+
Good for you!
|
55
|
+
MSG
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dalle
|
4
|
+
def dalle
|
5
|
+
attempt(3) do
|
6
|
+
prompt = @replies_to&.text || @text_without_command
|
7
|
+
send_chat_action(:upload_photo)
|
8
|
+
|
9
|
+
response = open_ai.images.generate(parameters: { prompt: prompt })
|
10
|
+
|
11
|
+
send_chat_action(:upload_photo)
|
12
|
+
|
13
|
+
url = response.dig("data", 0, "url")
|
14
|
+
|
15
|
+
if response["error"]
|
16
|
+
reply_code(response)
|
17
|
+
else
|
18
|
+
send_photo(url, reply_to_message_id: @msg.message_id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubydium"
|
4
|
+
require "openai"
|
5
|
+
require "down"
|
6
|
+
require "pry"
|
7
|
+
require_relative "chat_gpt"
|
8
|
+
require_relative "dalle"
|
9
|
+
require_relative "utils"
|
10
|
+
require_relative "whisper"
|
11
|
+
|
12
|
+
# I wrote the code "until it works" as I went without much refactoring,
|
13
|
+
# so yes, it's not great, especially the ChatGPT functionality.
|
14
|
+
class ChatGPTBot < Rubydium::Bot
|
15
|
+
include ChatGPT
|
16
|
+
include Dalle
|
17
|
+
include Utils
|
18
|
+
include Whisper
|
19
|
+
|
20
|
+
# Whenever mentioned or replied to, finds or creates a conversation thread
|
21
|
+
# for this chat, add your message to it and returns ChatGPT's response.
|
22
|
+
on_every_message :handle_gpt_command
|
23
|
+
# Whenever a voice message appears in the chat, uses Whisper to transcribe
|
24
|
+
# it and sends the result.
|
25
|
+
# Set `ignore_forwarded` to false to automatically react to forwarded voice messages
|
26
|
+
on_every_message :transcribe, ignore_forwarded: true
|
27
|
+
|
28
|
+
on_command "/start", :init_session, description: "Resets ChatGPT session"
|
29
|
+
on_command "/dalle", :dalle, description: "Sends the prompt to DALL-E"
|
30
|
+
on_command "/transcribe", :transcribe, description: "Reply to a voice message to transcribe it"
|
31
|
+
on_command "/pry", :pry, description: "Open a debug session in the terminal with the context of this message"
|
32
|
+
|
33
|
+
def pry
|
34
|
+
binding.pry
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def private_chat?
|
40
|
+
@chat.type == "private"
|
41
|
+
end
|
42
|
+
|
43
|
+
def bot_replied_to?
|
44
|
+
@target&.username == config.bot_username
|
45
|
+
end
|
46
|
+
|
47
|
+
def bot_mentioned?
|
48
|
+
@text.split(/\s/).first == "@#{config.bot_username}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def open_ai
|
52
|
+
config.open_ai_client
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ChatGPTBot.configure do |config|
|
57
|
+
config.token = "1234567890:long_alphanumeric_string_goes_here"
|
58
|
+
config.bot_username = "ends_with_bot"
|
59
|
+
config.owner_username = "thats_you"
|
60
|
+
config.chat_gpt_allow_all_group_chats = true
|
61
|
+
config.chat_gpt_allow_all_private_chats = true
|
62
|
+
config.open_ai_token = "sk-WWEt2TQQwRwT5Q6R11erE3TerrY65E2w4q5y1t4T2TwqYYyQ"
|
63
|
+
config.open_ai_client = OpenAI::Client.new(
|
64
|
+
access_token: config.open_ai_token
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
ChatGPTBot.run
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
def attempt(times, exception=Net::ReadTimeout)
|
5
|
+
retries ||= 0
|
6
|
+
yield
|
7
|
+
rescue exception => e
|
8
|
+
retries += 1
|
9
|
+
if retries < times
|
10
|
+
retry
|
11
|
+
else
|
12
|
+
reply_code(e.message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def download_file(voice)
|
17
|
+
file_path = @api.get_file(file_id: voice.file_id)["result"]["file_path"]
|
18
|
+
|
19
|
+
url = "https://api.telegram.org/file/bot#{config.token}/#{file_path}"
|
20
|
+
|
21
|
+
file = Down.download(url)
|
22
|
+
FileUtils.mv(file.path, "./#{file.original_filename}")
|
23
|
+
file
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Whisper
|
4
|
+
def transcribe
|
5
|
+
attempt(3) do
|
6
|
+
voice =
|
7
|
+
if @command == "/transcribe"
|
8
|
+
@replies_to&.voice
|
9
|
+
else
|
10
|
+
@msg.voice
|
11
|
+
end
|
12
|
+
|
13
|
+
return unless voice
|
14
|
+
|
15
|
+
send_chat_action(:typing)
|
16
|
+
|
17
|
+
file = ogg_to_mp3(download_file(voice))
|
18
|
+
response = send_whisper_request(file[:file])
|
19
|
+
|
20
|
+
if response["error"]
|
21
|
+
reply_code(response)
|
22
|
+
else
|
23
|
+
reply(response["text"])
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
FileUtils.rm_rf(file[:names]) if file
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ogg_to_mp3(file)
|
31
|
+
ogg = file.original_filename
|
32
|
+
mp3 = ogg.sub(/og.\z/, "mp3")
|
33
|
+
`ffmpeg -i ./#{ogg} -acodec libmp3lame ./#{mp3} -y`
|
34
|
+
{ file: File.open("./#{mp3}", "rb"), names: [ogg, mp3] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def send_whisper_request(file)
|
38
|
+
open_ai.audio.transcribe(
|
39
|
+
parameters: {
|
40
|
+
model: "whisper-1",
|
41
|
+
file: file
|
42
|
+
}
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
@@ -7,6 +7,7 @@ module Rubydium
|
|
7
7
|
def send_message(text)
|
8
8
|
@api.send_message(
|
9
9
|
chat_id: @chat.id,
|
10
|
+
message_thread_id: @msg.message_thread_id,
|
10
11
|
text: text
|
11
12
|
)
|
12
13
|
end
|
@@ -16,6 +17,7 @@ module Rubydium
|
|
16
17
|
|
17
18
|
@api.send_sticker(
|
18
19
|
chat_id: @chat.id,
|
20
|
+
message_thread_id: @msg.message_thread_id,
|
19
21
|
sticker: sticker,
|
20
22
|
**kwargs
|
21
23
|
)
|
@@ -32,6 +34,7 @@ module Rubydium
|
|
32
34
|
@api.send_chat_action(
|
33
35
|
chat_id: @chat.id,
|
34
36
|
action: action,
|
37
|
+
message_thread_id: @msg.message_thread_id,
|
35
38
|
**kwargs
|
36
39
|
)
|
37
40
|
end
|
@@ -41,6 +44,7 @@ module Rubydium
|
|
41
44
|
|
42
45
|
@api.send_video(
|
43
46
|
chat_id: @chat.id,
|
47
|
+
message_thread_id: @msg.message_thread_id,
|
44
48
|
video: video,
|
45
49
|
**kwargs
|
46
50
|
)
|
@@ -51,6 +55,7 @@ module Rubydium
|
|
51
55
|
|
52
56
|
@api.send_photo(
|
53
57
|
chat_id: @chat.id,
|
58
|
+
message_thread_id: @msg.message_thread_id,
|
54
59
|
photo: photo,
|
55
60
|
**kwargs
|
56
61
|
)
|
@@ -59,6 +64,7 @@ module Rubydium
|
|
59
64
|
def reply(text, **args)
|
60
65
|
@api.send_message(
|
61
66
|
chat_id: @chat.id,
|
67
|
+
message_thread_id: @msg.message_thread_id,
|
62
68
|
reply_to_message_id: @message_id,
|
63
69
|
text: text,
|
64
70
|
**args
|
@@ -72,6 +78,7 @@ module Rubydium
|
|
72
78
|
def reply_to_target(text)
|
73
79
|
@api.send_message(
|
74
80
|
chat_id: @chat.id,
|
81
|
+
message_thread_id: @msg.message_thread_id,
|
75
82
|
reply_to_message_id: @replies_to.message_id,
|
76
83
|
text: text
|
77
84
|
)
|
data/lib/rubydium/version.rb
CHANGED
data/rubydium.gemspec
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.metadata["rubygems_mfa_required"] = "true"
|
35
35
|
|
36
36
|
{
|
37
|
-
"telegram-bot-ruby" => ['~> 0.
|
37
|
+
"telegram-bot-ruby" => ['~> 1.0.0'],
|
38
38
|
"async" => ['~> 2.3']
|
39
39
|
}.each do |name, versions|
|
40
40
|
spec.add_dependency(name, *versions)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubydium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bulgakke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: telegram-bot-ruby
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 1.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 1.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: async
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -54,6 +54,13 @@ files:
|
|
54
54
|
- LICENSE
|
55
55
|
- README.md
|
56
56
|
- example/example_bot.rb
|
57
|
+
- example/open_ai_bot/Gemfile
|
58
|
+
- example/open_ai_bot/chat_gpt.rb
|
59
|
+
- example/open_ai_bot/chat_thread.rb
|
60
|
+
- example/open_ai_bot/dalle.rb
|
61
|
+
- example/open_ai_bot/open_ai_bot.rb
|
62
|
+
- example/open_ai_bot/utils.rb
|
63
|
+
- example/open_ai_bot/whisper.rb
|
57
64
|
- lib/rubydium.rb
|
58
65
|
- lib/rubydium/bot.rb
|
59
66
|
- lib/rubydium/config.rb
|