rubydium 0.4.4 → 0.4.6
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/.gitignore +1 -0
- data/.rubocop.yml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +7 -7
- data/Gemfile.lock +77 -65
- data/example/example_bot.rb +9 -9
- data/example/open_ai_bot/Gemfile +6 -6
- data/example/open_ai_bot/chat_gpt.rb +12 -11
- data/example/open_ai_bot/chat_thread.rb +2 -2
- data/example/open_ai_bot/dalle.rb +2 -2
- data/example/open_ai_bot/open_ai_bot.rb +18 -17
- data/example/open_ai_bot/utils.rb +1 -1
- data/example/open_ai_bot/whisper.rb +6 -6
- data/lib/rubydium/bot.rb +5 -5
- data/lib/rubydium/config.rb +2 -2
- data/lib/rubydium/mixins/command_macros.rb +15 -18
- data/lib/rubydium/mixins/message_sending.rb +24 -24
- data/lib/rubydium/mixins/other_actions.rb +6 -6
- data/lib/rubydium/mixins/rights_checking.rb +6 -3
- data/lib/rubydium/mixins.rb +5 -5
- data/lib/rubydium/version.rb +1 -1
- data/lib/rubydium.rb +6 -6
- data/rubydium.gemspec +14 -14
- metadata +3 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '081b0354f048af37584defdbc89e41ed137ed93b532cab71fce88836bde1dcd9'
|
4
|
+
data.tar.gz: ab8d0382e85443ae273b80f8aa657c0aab2ff899b1788a86f89732b5700a8b39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51866587d15c910e974256fc23895ca8e3815e42727c144b618f2c5592fb4478165bf6d08f60f310eebce48f3d8fa0b87c826a4f061dec58dd9fc5581609d97d
|
7
|
+
data.tar.gz: 8716186a1edfdf82b7013f35a6386e27b89fd30081c72b9f1f6c1229ecdf7097821befb95441bf9c025deb4ad847d01edea564909dcd2b86c267312b00b53e26
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require: rubocop-rspec
|
2
2
|
|
3
3
|
AllCops:
|
4
|
-
TargetRubyVersion: 3.1
|
4
|
+
TargetRubyVersion: 3.4.1
|
5
5
|
NewCops: enable
|
6
6
|
Exclude:
|
7
7
|
- test.rb
|
8
8
|
|
9
|
+
FactoryBot/IdSequence:
|
10
|
+
Enabled: false
|
11
|
+
|
9
12
|
Layout/LineLength:
|
10
13
|
Max: 100
|
11
14
|
|
@@ -57,6 +60,3 @@ Style/HashSyntax:
|
|
57
60
|
|
58
61
|
Style/IfUnlessModifier:
|
59
62
|
Enabled: false
|
60
|
-
|
61
|
-
Style/StringLiterals:
|
62
|
-
EnforcedStyle: double_quotes
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.4.1
|
data/Gemfile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source 'https://rubygems.org'
|
4
4
|
|
5
5
|
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
6
6
|
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
10
|
-
gem
|
11
|
-
gem
|
12
|
-
gem
|
7
|
+
gem 'async'
|
8
|
+
gem 'factory_bot'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'rubocop'
|
11
|
+
gem 'rubocop-rspec'
|
12
|
+
gem 'telegram-bot-ruby', '~> 2.2'
|
data/Gemfile.lock
CHANGED
@@ -1,118 +1,130 @@
|
|
1
1
|
GEM
|
2
2
|
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
+
activesupport (8.0.1)
|
5
|
+
base64
|
6
|
+
benchmark (>= 0.3)
|
7
|
+
bigdecimal
|
8
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
9
|
+
connection_pool (>= 2.2.5)
|
10
|
+
drb
|
11
|
+
i18n (>= 1.6, < 2)
|
12
|
+
logger (>= 1.4.2)
|
13
|
+
minitest (>= 5.1)
|
14
|
+
securerandom (>= 0.3)
|
15
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
16
|
+
uri (>= 0.13.1)
|
4
17
|
ast (2.4.2)
|
5
|
-
async (2.
|
6
|
-
console (~> 1.
|
18
|
+
async (2.21.1)
|
19
|
+
console (~> 1.29)
|
7
20
|
fiber-annotation
|
8
|
-
io-event (~> 1.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
concurrent-ruby (1.3.
|
13
|
-
|
21
|
+
io-event (~> 1.6, >= 1.6.5)
|
22
|
+
base64 (0.2.0)
|
23
|
+
benchmark (0.4.0)
|
24
|
+
bigdecimal (3.1.9)
|
25
|
+
concurrent-ruby (1.3.5)
|
26
|
+
connection_pool (2.5.0)
|
27
|
+
console (1.29.2)
|
14
28
|
fiber-annotation
|
15
29
|
fiber-local (~> 1.1)
|
16
30
|
json
|
17
31
|
diff-lcs (1.5.1)
|
18
|
-
|
32
|
+
drb (2.2.1)
|
33
|
+
dry-core (1.1.0)
|
19
34
|
concurrent-ruby (~> 1.0)
|
35
|
+
logger
|
20
36
|
zeitwerk (~> 2.6)
|
21
|
-
dry-inflector (1.
|
22
|
-
dry-logic (1.
|
37
|
+
dry-inflector (1.2.0)
|
38
|
+
dry-logic (1.6.0)
|
39
|
+
bigdecimal
|
23
40
|
concurrent-ruby (~> 1.0)
|
24
|
-
dry-core (~> 1.
|
41
|
+
dry-core (~> 1.1)
|
25
42
|
zeitwerk (~> 2.6)
|
26
|
-
dry-struct (1.
|
27
|
-
dry-core (~> 1.
|
28
|
-
dry-types (
|
43
|
+
dry-struct (1.7.0)
|
44
|
+
dry-core (~> 1.1)
|
45
|
+
dry-types (~> 1.8)
|
29
46
|
ice_nine (~> 0.11)
|
30
47
|
zeitwerk (~> 2.6)
|
31
|
-
dry-types (1.
|
48
|
+
dry-types (1.8.1)
|
32
49
|
bigdecimal (~> 3.0)
|
33
50
|
concurrent-ruby (~> 1.0)
|
34
51
|
dry-core (~> 1.0)
|
35
52
|
dry-inflector (~> 1.0)
|
36
53
|
dry-logic (~> 1.4)
|
37
54
|
zeitwerk (~> 2.6)
|
38
|
-
|
39
|
-
|
40
|
-
faraday
|
41
|
-
|
42
|
-
|
43
|
-
|
55
|
+
factory_bot (6.5.0)
|
56
|
+
activesupport (>= 5.0.0)
|
57
|
+
faraday (2.12.2)
|
58
|
+
faraday-net_http (>= 2.0, < 3.5)
|
59
|
+
json
|
60
|
+
logger
|
61
|
+
faraday-multipart (1.1.0)
|
62
|
+
multipart-post (~> 2.0)
|
63
|
+
faraday-net_http (3.4.0)
|
64
|
+
net-http (>= 0.5.0)
|
44
65
|
fiber-annotation (0.2.0)
|
45
66
|
fiber-local (1.1.0)
|
46
67
|
fiber-storage
|
47
|
-
fiber-storage (0.
|
68
|
+
fiber-storage (1.0.0)
|
69
|
+
i18n (1.14.7)
|
70
|
+
concurrent-ruby (~> 1.0)
|
48
71
|
ice_nine (0.11.2)
|
49
|
-
io-event (1.
|
50
|
-
json (2.
|
72
|
+
io-event (1.7.5)
|
73
|
+
json (2.9.1)
|
51
74
|
language_server-protocol (3.17.0.3)
|
52
|
-
|
75
|
+
logger (1.6.5)
|
76
|
+
minitest (5.25.4)
|
53
77
|
multipart-post (2.4.1)
|
54
|
-
net-http (0.
|
78
|
+
net-http (0.6.0)
|
55
79
|
uri
|
56
|
-
parallel (1.
|
57
|
-
parser (3.3.
|
80
|
+
parallel (1.26.3)
|
81
|
+
parser (3.3.7.0)
|
58
82
|
ast (~> 2.4.1)
|
59
83
|
racc
|
60
|
-
|
61
|
-
coderay (~> 1.1)
|
62
|
-
method_source (~> 1.0)
|
63
|
-
racc (1.8.0)
|
84
|
+
racc (1.8.1)
|
64
85
|
rainbow (3.1.1)
|
65
|
-
regexp_parser (2.
|
66
|
-
rexml (3.2.8)
|
67
|
-
strscan (>= 3.0.9)
|
86
|
+
regexp_parser (2.10.0)
|
68
87
|
rspec (3.13.0)
|
69
88
|
rspec-core (~> 3.13.0)
|
70
89
|
rspec-expectations (~> 3.13.0)
|
71
90
|
rspec-mocks (~> 3.13.0)
|
72
|
-
rspec-core (3.13.
|
91
|
+
rspec-core (3.13.2)
|
73
92
|
rspec-support (~> 3.13.0)
|
74
|
-
rspec-expectations (3.13.
|
93
|
+
rspec-expectations (3.13.3)
|
75
94
|
diff-lcs (>= 1.2.0, < 2.0)
|
76
95
|
rspec-support (~> 3.13.0)
|
77
|
-
rspec-mocks (3.13.
|
96
|
+
rspec-mocks (3.13.2)
|
78
97
|
diff-lcs (>= 1.2.0, < 2.0)
|
79
98
|
rspec-support (~> 3.13.0)
|
80
|
-
rspec-support (3.13.
|
81
|
-
rubocop (1.
|
99
|
+
rspec-support (3.13.2)
|
100
|
+
rubocop (1.71.0)
|
82
101
|
json (~> 2.3)
|
83
102
|
language_server-protocol (>= 3.17.0)
|
84
103
|
parallel (~> 1.10)
|
85
104
|
parser (>= 3.3.0.2)
|
86
105
|
rainbow (>= 2.2.2, < 4.0)
|
87
|
-
regexp_parser (>=
|
88
|
-
|
89
|
-
rubocop-ast (>= 1.31.1, < 2.0)
|
106
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
107
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
90
108
|
ruby-progressbar (~> 1.7)
|
91
|
-
unicode-display_width (>= 2.4.0, <
|
92
|
-
rubocop-ast (1.
|
109
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
110
|
+
rubocop-ast (1.37.0)
|
93
111
|
parser (>= 3.3.1.0)
|
94
|
-
rubocop-
|
95
|
-
rubocop (~> 1.
|
96
|
-
rubocop-factory_bot (2.25.1)
|
97
|
-
rubocop (~> 1.41)
|
98
|
-
rubocop-rspec (2.30.0)
|
99
|
-
rubocop (~> 1.40)
|
100
|
-
rubocop-capybara (~> 2.17)
|
101
|
-
rubocop-factory_bot (~> 2.22)
|
102
|
-
rubocop-rspec_rails (~> 2.28)
|
103
|
-
rubocop-rspec_rails (2.28.3)
|
104
|
-
rubocop (~> 1.40)
|
112
|
+
rubocop-rspec (3.4.0)
|
113
|
+
rubocop (~> 1.61)
|
105
114
|
ruby-progressbar (1.13.0)
|
106
|
-
|
107
|
-
telegram-bot-ruby (
|
115
|
+
securerandom (0.4.1)
|
116
|
+
telegram-bot-ruby (2.2.0)
|
108
117
|
dry-struct (~> 1.6)
|
109
118
|
faraday (~> 2.0)
|
110
119
|
faraday-multipart (~> 1.0)
|
111
120
|
zeitwerk (~> 2.6)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
121
|
+
tzinfo (2.0.6)
|
122
|
+
concurrent-ruby (~> 1.0)
|
123
|
+
unicode-display_width (3.1.4)
|
124
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
125
|
+
unicode-emoji (4.0.4)
|
126
|
+
uri (1.0.2)
|
127
|
+
zeitwerk (2.7.1)
|
116
128
|
|
117
129
|
PLATFORMS
|
118
130
|
ruby
|
@@ -120,11 +132,11 @@ PLATFORMS
|
|
120
132
|
|
121
133
|
DEPENDENCIES
|
122
134
|
async
|
123
|
-
|
135
|
+
factory_bot
|
124
136
|
rspec
|
125
137
|
rubocop
|
126
138
|
rubocop-rspec
|
127
|
-
telegram-bot-ruby (~>
|
139
|
+
telegram-bot-ruby (~> 2.2)
|
128
140
|
|
129
141
|
BUNDLED WITH
|
130
142
|
2.5.3
|
data/example/example_bot.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'rubydium'
|
4
|
+
require 'pry'
|
5
5
|
|
6
6
|
# Your actual logic of handling the updates goes here.
|
7
7
|
class ExampleBot < Rubydium::Bot
|
8
8
|
on_every_message :log_message
|
9
9
|
|
10
|
-
on_command
|
10
|
+
on_command '/help', description: 'Show help message' do
|
11
11
|
text = self.class.help_message
|
12
12
|
send_message(text)
|
13
13
|
end
|
14
14
|
|
15
|
-
on_command
|
16
|
-
on_command
|
15
|
+
on_command '/start', :greet_user, description: 'Say hello'
|
16
|
+
on_command '/pry' do
|
17
17
|
binding.pry
|
18
18
|
end
|
19
19
|
|
@@ -22,15 +22,15 @@ class ExampleBot < Rubydium::Bot
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def greet_user
|
25
|
-
text =
|
25
|
+
text = 'Hi hello'
|
26
26
|
reply(text)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
ExampleBot.configure do |config|
|
31
|
-
config.token =
|
32
|
-
config.bot_username =
|
33
|
-
config.owner_username =
|
31
|
+
config.token = '1234567890:long_alphanumeric_string_goes_here'
|
32
|
+
config.bot_username = 'ends_with_bot'
|
33
|
+
config.owner_username = 'thats_you'
|
34
34
|
config.privileged_usernames = %w[
|
35
35
|
your_friend your_chat_moderator
|
36
36
|
]
|
data/example/open_ai_bot/Gemfile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source 'https://rubygems.org'
|
4
4
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
5
|
+
gem 'down', '~> 5.4'
|
6
|
+
gem 'http', '~> 5.1'
|
7
|
+
gem 'pry', '~> 0.14.2'
|
8
|
+
gem 'rubydium', '>= 0.2.3'
|
9
|
+
gem 'ruby-openai', '~> 5.1'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'chat_thread'
|
4
4
|
|
5
5
|
module ChatGPT
|
6
6
|
module ClassMethods
|
@@ -37,13 +37,13 @@ module ChatGPT
|
|
37
37
|
return if self.class.registered_commands.keys.any? { @text.match? Regexp.new(_1) }
|
38
38
|
return unless bot_mentioned? || bot_replied_to? || private_chat?
|
39
39
|
|
40
|
-
|
40
|
+
unless allowed_chat?
|
41
41
|
msg = "This chat (`#{@chat.id}`) is not whitelisted for ChatGPT usage. Ask @#{config.owner_username}."
|
42
|
-
return reply(msg, parse_mode:
|
42
|
+
return reply(msg, parse_mode: 'Markdown')
|
43
43
|
end
|
44
44
|
|
45
45
|
text = @text_without_bot_mentions
|
46
|
-
text = nil if text.gsub(/\s/,
|
46
|
+
text = nil if text.gsub(/\s/, '').empty?
|
47
47
|
|
48
48
|
target_text = @replies_to&.text || @replies_to&.caption
|
49
49
|
target_text = nil if @target&.username == config.bot_username
|
@@ -74,18 +74,19 @@ module ChatGPT
|
|
74
74
|
attempt(3) do
|
75
75
|
response = open_ai.chat(
|
76
76
|
parameters: {
|
77
|
-
model:
|
77
|
+
model: 'gpt-3.5-turbo',
|
78
78
|
messages: thread.history
|
79
79
|
}
|
80
80
|
)
|
81
81
|
|
82
|
-
if response[
|
83
|
-
error_text = response[
|
84
|
-
error_text
|
85
|
-
raise Net::ReadTimeout, response[
|
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
86
|
else
|
87
|
-
text = response.dig(
|
88
|
-
puts "#{Time.now.to_i} | Chat ID: #{@chat.id}, tokens used: #{response.dig(
|
87
|
+
text = response.dig('choices', 0, 'message', 'content')
|
88
|
+
puts "#{Time.now.to_i} | Chat ID: #{@chat.id}, tokens used: #{response.dig('usage',
|
89
|
+
'total_tokens')}"
|
89
90
|
|
90
91
|
reply(text)
|
91
92
|
thread.add!(:assistant, text)
|
@@ -21,10 +21,10 @@ class ChatThread
|
|
21
21
|
attr_reader :history
|
22
22
|
|
23
23
|
def add!(role, content)
|
24
|
-
return if [role, content].any? { [nil,
|
24
|
+
return if [role, content].any? { [nil, ''].include?(_1) }
|
25
25
|
|
26
26
|
@history.push({
|
27
|
-
role: role, content: content.gsub(/\\xD\d/,
|
27
|
+
role: role, content: content.gsub(/\\xD\d/, '')
|
28
28
|
})
|
29
29
|
end
|
30
30
|
|
@@ -10,9 +10,9 @@ module Dalle
|
|
10
10
|
|
11
11
|
send_chat_action(:upload_photo)
|
12
12
|
|
13
|
-
url = response.dig(
|
13
|
+
url = response.dig('data', 0, 'url')
|
14
14
|
|
15
|
-
if response[
|
15
|
+
if response['error']
|
16
16
|
reply_code(response)
|
17
17
|
else
|
18
18
|
send_photo(url, reply_to_message_id: @msg.message_id)
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
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
11
|
|
12
12
|
# I wrote the code "until it works" as I went without much refactoring,
|
13
13
|
# so yes, it's not great, especially the ChatGPT functionality.
|
@@ -25,10 +25,11 @@ class ChatGPTBot < Rubydium::Bot
|
|
25
25
|
# Set `ignore_forwarded` to false to automatically react to forwarded voice messages
|
26
26
|
on_every_message :transcribe, ignore_forwarded: true
|
27
27
|
|
28
|
-
on_command
|
29
|
-
on_command
|
30
|
-
on_command
|
31
|
-
on_command
|
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,
|
32
|
+
description: 'Open a debug session in the terminal with the context of this message'
|
32
33
|
|
33
34
|
def pry
|
34
35
|
binding.pry
|
@@ -37,7 +38,7 @@ class ChatGPTBot < Rubydium::Bot
|
|
37
38
|
private
|
38
39
|
|
39
40
|
def private_chat?
|
40
|
-
@chat.type ==
|
41
|
+
@chat.type == 'private'
|
41
42
|
end
|
42
43
|
|
43
44
|
def bot_replied_to?
|
@@ -54,12 +55,12 @@ class ChatGPTBot < Rubydium::Bot
|
|
54
55
|
end
|
55
56
|
|
56
57
|
ChatGPTBot.configure do |config|
|
57
|
-
config.token =
|
58
|
-
config.bot_username =
|
59
|
-
config.owner_username =
|
58
|
+
config.token = '1234567890:long_alphanumeric_string_goes_here'
|
59
|
+
config.bot_username = 'ends_with_bot'
|
60
|
+
config.owner_username = 'thats_you'
|
60
61
|
config.chat_gpt_allow_all_group_chats = true
|
61
62
|
config.chat_gpt_allow_all_private_chats = true
|
62
|
-
config.open_ai_token =
|
63
|
+
config.open_ai_token = 'sk-WWEt2TQQwRwT5Q6R11erE3TerrY65E2w4q5y1t4T2TwqYYyQ'
|
63
64
|
config.open_ai_client = OpenAI::Client.new(
|
64
65
|
access_token: config.open_ai_token
|
65
66
|
)
|
@@ -14,7 +14,7 @@ module Utils
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def download_file(voice)
|
17
|
-
file_path = @api.get_file(file_id: voice.file_id)[
|
17
|
+
file_path = @api.get_file(file_id: voice.file_id)['result']['file_path']
|
18
18
|
|
19
19
|
url = "https://api.telegram.org/file/bot#{config.token}/#{file_path}"
|
20
20
|
|
@@ -4,7 +4,7 @@ module Whisper
|
|
4
4
|
def transcribe
|
5
5
|
attempt(3) do
|
6
6
|
voice =
|
7
|
-
if @command ==
|
7
|
+
if @command == '/transcribe'
|
8
8
|
@replies_to&.voice
|
9
9
|
else
|
10
10
|
@msg.voice
|
@@ -17,10 +17,10 @@ module Whisper
|
|
17
17
|
file = ogg_to_mp3(download_file(voice))
|
18
18
|
response = send_whisper_request(file[:file])
|
19
19
|
|
20
|
-
if response[
|
20
|
+
if response['error']
|
21
21
|
reply_code(response)
|
22
22
|
else
|
23
|
-
reply(response[
|
23
|
+
reply(response['text'])
|
24
24
|
end
|
25
25
|
ensure
|
26
26
|
FileUtils.rm_rf(file[:names]) if file
|
@@ -29,15 +29,15 @@ module Whisper
|
|
29
29
|
|
30
30
|
def ogg_to_mp3(file)
|
31
31
|
ogg = file.original_filename
|
32
|
-
mp3 = ogg.sub(/og.\z/,
|
32
|
+
mp3 = ogg.sub(/og.\z/, 'mp3')
|
33
33
|
`ffmpeg -i ./#{ogg} -acodec libmp3lame ./#{mp3} -y`
|
34
|
-
{ file: File.open("./#{mp3}",
|
34
|
+
{ file: File.open("./#{mp3}", 'rb'), names: [ogg, mp3] }
|
35
35
|
end
|
36
36
|
|
37
37
|
def send_whisper_request(file)
|
38
38
|
open_ai.audio.transcribe(
|
39
39
|
parameters: {
|
40
|
-
model:
|
40
|
+
model: 'whisper-1',
|
41
41
|
file: file
|
42
42
|
}
|
43
43
|
)
|
data/lib/rubydium/bot.rb
CHANGED
@@ -11,7 +11,7 @@ module Rubydium
|
|
11
11
|
|
12
12
|
def self.fetch_and_set_bot_id(client)
|
13
13
|
configure do |config|
|
14
|
-
config.bot_id = client.api.get_me.
|
14
|
+
config.bot_id = client.api.get_me.id unless config.respond_to? :bot_id
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -25,7 +25,7 @@ module Rubydium
|
|
25
25
|
# Not all `update`s here are messages (`listen` yields `Update#current_message`,
|
26
26
|
# which can be `ChatMemberUpdated` etc.)
|
27
27
|
# TODO: rework to allow for clean handling of other types.
|
28
|
-
if update.is_a?
|
28
|
+
if update.is_a? Telegram::Bot::Types::Message
|
29
29
|
new(client, update).handle_update
|
30
30
|
end
|
31
31
|
rescue StandardError => e
|
@@ -49,9 +49,9 @@ module Rubydium
|
|
49
49
|
@text = (@msg.text || @msg.caption).to_s
|
50
50
|
@message_id = @msg.message_id
|
51
51
|
@command = get_command(@msg.text || @msg.caption)
|
52
|
-
@text_without_command = @text.gsub(@command.to_s,
|
53
|
-
|
54
|
-
@text_without_bot_mentions = @text.gsub(/@#{config.bot_username}\b/,
|
52
|
+
@text_without_command = @text.gsub(@command.to_s, '').gsub(/@#{config.bot_username}\b/,
|
53
|
+
'').strip
|
54
|
+
@text_without_bot_mentions = @text.gsub(/@#{config.bot_username}\b/, '')
|
55
55
|
end
|
56
56
|
|
57
57
|
def handle_update
|
data/lib/rubydium/config.rb
CHANGED
@@ -25,11 +25,11 @@ module Rubydium
|
|
25
25
|
# Not necessary for basic functionality, though.
|
26
26
|
class Config
|
27
27
|
def method_missing(method, ...)
|
28
|
-
if method[-1] ==
|
28
|
+
if method[-1] == '='
|
29
29
|
self.class.attr_accessor method[0..-2]
|
30
30
|
public_send(method, ...)
|
31
31
|
else
|
32
|
-
super
|
32
|
+
super
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -46,8 +46,8 @@ module Rubydium
|
|
46
46
|
|
47
47
|
def on_mention(method_name=nil, ignore_forwarded: true, &block)
|
48
48
|
@registered_on_mention ||= []
|
49
|
-
action =
|
50
|
-
raise ArgumentError,
|
49
|
+
action = method_name || block
|
50
|
+
raise ArgumentError, 'Provide either method name or a block' unless action
|
51
51
|
|
52
52
|
@registered_on_mention << {
|
53
53
|
action: action,
|
@@ -61,8 +61,8 @@ module Rubydium
|
|
61
61
|
|
62
62
|
def on_every_message(method_name=nil, ignore_forwarded: true, &block)
|
63
63
|
@registered_on_every_message ||= []
|
64
|
-
action =
|
65
|
-
raise ArgumentError,
|
64
|
+
action = method_name || block
|
65
|
+
raise ArgumentError, 'Provide either method name or a block' unless action
|
66
66
|
|
67
67
|
@registered_on_every_message << {
|
68
68
|
action: action,
|
@@ -74,10 +74,11 @@ module Rubydium
|
|
74
74
|
@registered_on_every_message ||= []
|
75
75
|
end
|
76
76
|
|
77
|
-
def on_command(command, method_name=nil, aliases: [], description: nil,
|
77
|
+
def on_command(command, method_name=nil, aliases: [], description: nil,
|
78
|
+
ignore_forwarded: true, &block)
|
78
79
|
@registered_commands ||= {}
|
79
|
-
action =
|
80
|
-
raise ArgumentError,
|
80
|
+
action = method_name || block
|
81
|
+
raise ArgumentError, 'Provide either method name or a block' unless action
|
81
82
|
|
82
83
|
parameters = {
|
83
84
|
action: action,
|
@@ -86,9 +87,9 @@ module Rubydium
|
|
86
87
|
}
|
87
88
|
|
88
89
|
@registered_commands.merge!(
|
89
|
-
[command, *aliases].
|
90
|
+
[command, *aliases].to_h do |comm|
|
90
91
|
[comm, parameters]
|
91
|
-
|
92
|
+
end
|
92
93
|
)
|
93
94
|
end
|
94
95
|
|
@@ -97,22 +98,18 @@ module Rubydium
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
100
|
-
def skip_task(**kwargs)
|
101
|
-
kwargs.each_pair do |task_type, task_name|
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
101
|
def execute_on_every_message
|
107
102
|
self.class.registered_on_every_message.each do |action|
|
108
|
-
next if action[:ignore_forwarded] && @msg.
|
103
|
+
next if action[:ignore_forwarded] && @msg.forward_origin
|
104
|
+
|
109
105
|
execute_action(action[:action])
|
110
106
|
end
|
111
107
|
end
|
112
108
|
|
113
109
|
def execute_on_mention
|
114
110
|
self.class.registered_on_mention.each do |action|
|
115
|
-
next if action[:ignore_forwarded] && @msg.
|
111
|
+
next if action[:ignore_forwarded] && @msg.forward_origin
|
112
|
+
|
116
113
|
execute_action(action[:action])
|
117
114
|
end
|
118
115
|
end
|
@@ -120,7 +117,7 @@ module Rubydium
|
|
120
117
|
def execute_command
|
121
118
|
command = self.class.registered_commands[@command]
|
122
119
|
return unless command
|
123
|
-
return if command[:ignore_forwarded] && @msg.
|
120
|
+
return if command[:ignore_forwarded] && @msg.forward_origin
|
124
121
|
|
125
122
|
action = command[:action]
|
126
123
|
|
@@ -10,21 +10,21 @@ module Rubydium
|
|
10
10
|
(string.length / size.to_f).ceil.times.map { |i| string[i * size, size] }
|
11
11
|
end
|
12
12
|
|
13
|
-
def send_message(text, split: false, **
|
14
|
-
return send_many_messages(text, **
|
13
|
+
def send_message(text, split: false, **)
|
14
|
+
return send_many_messages(text, **) if split
|
15
15
|
|
16
16
|
@api.send_message(
|
17
17
|
chat_id: @chat.id,
|
18
18
|
message_thread_id: @topic_id,
|
19
19
|
text: text,
|
20
|
-
**
|
20
|
+
**
|
21
21
|
)
|
22
22
|
rescue Telegram::Bot::Exceptions::ResponseError => e
|
23
23
|
data = e.send(:data)
|
24
|
-
raise e unless data[
|
24
|
+
raise e unless data['error_code'] == 429
|
25
25
|
|
26
|
-
retry_after = data.dig(
|
27
|
-
raise e unless retry_after
|
26
|
+
retry_after = data.dig('parameters', 'retry_after')
|
27
|
+
raise e unless retry_after&.positive?
|
28
28
|
|
29
29
|
sleep retry_after
|
30
30
|
retry
|
@@ -33,77 +33,77 @@ module Rubydium
|
|
33
33
|
def send_many_messages(text, **kwargs)
|
34
34
|
text_chunks = chunks(text, MAX_MESSAGE_SIZE)
|
35
35
|
|
36
|
-
text_chunks.map do |
|
36
|
+
text_chunks.map do |_chunk|
|
37
37
|
send_message(text, **kwargs)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def send_sticker(sticker, action: nil, **
|
41
|
+
def send_sticker(sticker, action: nil, **)
|
42
42
|
chat_action_if_provided(action, :choose_sticker)
|
43
43
|
|
44
44
|
@api.send_sticker(
|
45
45
|
chat_id: @chat.id,
|
46
46
|
message_thread_id: @topic_id,
|
47
47
|
sticker: sticker,
|
48
|
-
**
|
48
|
+
**
|
49
49
|
)
|
50
50
|
end
|
51
51
|
|
52
52
|
def chat_action_if_provided(duration, action_name)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
return unless duration
|
54
|
+
|
55
|
+
send_chat_action(action_name)
|
56
|
+
sleep duration if duration.is_a? Numeric
|
57
57
|
end
|
58
58
|
|
59
|
-
def send_chat_action(action, **
|
59
|
+
def send_chat_action(action, **)
|
60
60
|
@api.send_chat_action(
|
61
61
|
chat_id: @chat.id,
|
62
62
|
action: action,
|
63
63
|
message_thread_id: @topic_id,
|
64
|
-
**
|
64
|
+
**
|
65
65
|
)
|
66
66
|
end
|
67
67
|
|
68
|
-
def send_video(video, action: nil, **
|
68
|
+
def send_video(video, action: nil, **)
|
69
69
|
chat_action_if_provided(action, :upload_video)
|
70
70
|
|
71
71
|
@api.send_video(
|
72
72
|
chat_id: @chat.id,
|
73
73
|
message_thread_id: @topic_id,
|
74
74
|
video: video,
|
75
|
-
**
|
75
|
+
**
|
76
76
|
)
|
77
77
|
end
|
78
78
|
|
79
|
-
def send_photo(photo, action: nil, **
|
79
|
+
def send_photo(photo, action: nil, **)
|
80
80
|
chat_action_if_provided(action, :upload_photo)
|
81
81
|
|
82
82
|
@api.send_photo(
|
83
83
|
chat_id: @chat.id,
|
84
84
|
message_thread_id: @topic_id,
|
85
85
|
photo: photo,
|
86
|
-
**
|
86
|
+
**
|
87
87
|
)
|
88
88
|
end
|
89
89
|
|
90
|
-
def reply(text, **
|
90
|
+
def reply(text, **)
|
91
91
|
send_message(
|
92
92
|
text,
|
93
93
|
reply_to_message_id: @message_id,
|
94
|
-
**
|
94
|
+
**
|
95
95
|
)
|
96
96
|
end
|
97
97
|
|
98
98
|
def reply_code(text)
|
99
|
-
reply("```\n#{text}```", parse_mode:
|
99
|
+
reply("```\n#{text}```", parse_mode: 'Markdown')
|
100
100
|
end
|
101
101
|
|
102
|
-
def reply_to_target(text, **
|
102
|
+
def reply_to_target(text, **)
|
103
103
|
send_message(
|
104
104
|
text,
|
105
105
|
reply_to_message_id: @replies_to.message_id,
|
106
|
-
**
|
106
|
+
**
|
107
107
|
)
|
108
108
|
end
|
109
109
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rubydium
|
2
4
|
module Mixins
|
3
5
|
module OtherActions
|
@@ -14,7 +16,7 @@ module Rubydium
|
|
14
16
|
return false unless bot_can_delete_messages? || from_bot
|
15
17
|
|
16
18
|
result = @api.delete_message(chat_id: @chat.id, message_id: id)
|
17
|
-
result[
|
19
|
+
result['ok']
|
18
20
|
rescue Telegram::Bot::Exceptions::ResponseError
|
19
21
|
false
|
20
22
|
end
|
@@ -22,12 +24,10 @@ module Rubydium
|
|
22
24
|
def definitely_message(maybe_message)
|
23
25
|
return maybe_message if maybe_message.is_a? Telegram::Bot::Types::Message
|
24
26
|
|
25
|
-
if maybe_message[
|
27
|
+
if maybe_message['message_id']
|
26
28
|
Telegram::Bot::Types::Message.new(maybe_message)
|
27
|
-
elsif maybe_message[
|
28
|
-
Telegram::Bot::Types::Message.new(maybe_message[
|
29
|
-
else
|
30
|
-
nil
|
29
|
+
elsif maybe_message['result']['message_id']
|
30
|
+
Telegram::Bot::Types::Message.new(maybe_message['result'])
|
31
31
|
end
|
32
32
|
rescue StandardError
|
33
33
|
nil
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rubydium
|
2
4
|
module Mixins
|
3
5
|
module RightsChecking
|
@@ -5,7 +7,8 @@ module Rubydium
|
|
5
7
|
@user_info ||= {}
|
6
8
|
return @user_info[user_id] if @user_info[user_id]
|
7
9
|
|
8
|
-
@user_info[user_id] =
|
10
|
+
@user_info[user_id] =
|
11
|
+
@api.get_chat_member(chat_id: @chat.id, user_id: user_id)['result']
|
9
12
|
end
|
10
13
|
|
11
14
|
boolean_permissions = %w[
|
@@ -25,7 +28,7 @@ module Rubydium
|
|
25
28
|
|
26
29
|
boolean_permissions.each do |permission|
|
27
30
|
define_method "#{permission}?" do |user_id|
|
28
|
-
user_info(user_id)
|
31
|
+
user_info(user_id)[permission] || user_info(user_id)['status'] == 'creator'
|
29
32
|
end
|
30
33
|
|
31
34
|
define_method "bot_#{permission}?" do
|
@@ -37,7 +40,7 @@ module Rubydium
|
|
37
40
|
|
38
41
|
other_fields.each do |field|
|
39
42
|
define_method field do |user_id|
|
40
|
-
user_info(user_id)
|
43
|
+
user_info(user_id)[field]
|
41
44
|
end
|
42
45
|
|
43
46
|
define_method "bot_#{field}" do
|
data/lib/rubydium/mixins.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
3
|
+
require_relative 'mixins/message_sending'
|
4
|
+
require_relative 'mixins/command_macros'
|
5
|
+
require_relative 'mixins/control_flow'
|
6
|
+
require_relative 'mixins/other_actions'
|
7
|
+
require_relative 'mixins/rights_checking'
|
8
8
|
|
9
9
|
module Rubydium
|
10
10
|
module Mixins # :nodoc:
|
data/lib/rubydium/version.rb
CHANGED
data/lib/rubydium.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
3
|
+
require 'telegram/bot'
|
4
|
+
require 'async'
|
5
|
+
require_relative 'rubydium/mixins'
|
6
|
+
require_relative 'rubydium/bot'
|
7
|
+
require_relative 'rubydium/config'
|
8
|
+
require_relative 'rubydium/version'
|
9
9
|
|
10
10
|
module Rubydium # :nodoc:
|
11
11
|
end
|
data/rubydium.gemspec
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'lib/rubydium/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
6
|
+
spec.name = 'rubydium'
|
7
7
|
spec.version = Rubydium::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
8
|
+
spec.authors = ['bulgakke']
|
9
|
+
spec.email = ['be.evgeniy.bulavin@gmail.com']
|
10
10
|
|
11
11
|
spec.summary = "An OO framework for building Telegram bots. That's the plan, at least."
|
12
12
|
# spec.description = "TODO: Write a longer description or delete this line."
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new(
|
13
|
+
spec.homepage = 'https://github.com/bulgakke/rubydium'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.1.0')
|
16
16
|
|
17
17
|
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
18
18
|
|
19
|
-
spec.metadata[
|
20
|
-
spec.metadata[
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/bulgakke/rubydium'
|
21
21
|
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
22
22
|
|
23
23
|
# Specify which files should be added to the gem when it is released.
|
@@ -25,17 +25,17 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
26
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
27
27
|
end
|
28
|
-
spec.bindir =
|
28
|
+
spec.bindir = 'exe'
|
29
29
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = [
|
30
|
+
spec.require_paths = ['lib']
|
31
31
|
|
32
32
|
# For more information and examples about making a new gem, checkout our
|
33
33
|
# guide at: https://bundler.io/guides/creating_gem.html
|
34
|
-
spec.metadata[
|
34
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
35
35
|
|
36
36
|
{
|
37
|
-
|
38
|
-
|
37
|
+
'telegram-bot-ruby' => ['~> 1.0.0'],
|
38
|
+
'async' => ['~> 2.3']
|
39
39
|
}.each do |name, versions|
|
40
40
|
spec.add_dependency(name, *versions)
|
41
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubydium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bulgakke
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-06-29 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: telegram-bot-ruby
|
@@ -38,7 +37,6 @@ dependencies:
|
|
38
37
|
- - "~>"
|
39
38
|
- !ruby/object:Gem::Version
|
40
39
|
version: '2.3'
|
41
|
-
description:
|
42
40
|
email:
|
43
41
|
- be.evgeniy.bulavin@gmail.com
|
44
42
|
executables: []
|
@@ -79,7 +77,6 @@ metadata:
|
|
79
77
|
homepage_uri: https://github.com/bulgakke/rubydium
|
80
78
|
source_code_uri: https://github.com/bulgakke/rubydium
|
81
79
|
rubygems_mfa_required: 'true'
|
82
|
-
post_install_message:
|
83
80
|
rdoc_options: []
|
84
81
|
require_paths:
|
85
82
|
- lib
|
@@ -94,8 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
91
|
- !ruby/object:Gem::Version
|
95
92
|
version: '0'
|
96
93
|
requirements: []
|
97
|
-
rubygems_version: 3.
|
98
|
-
signing_key:
|
94
|
+
rubygems_version: 3.6.2
|
99
95
|
specification_version: 4
|
100
96
|
summary: An OO framework for building Telegram bots. That's the plan, at least.
|
101
97
|
test_files: []
|