slack-smart-bot 1.14.2 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +222 -37
- data/img/chat_gpt.png +0 -0
- data/img/chat_gpt_session.png +0 -0
- data/img/chat_gpt_share.png +0 -0
- data/img/command_add_sc.png +0 -0
- data/img/command_bot_help_echo.png +0 -0
- data/img/command_loop.png +0 -0
- data/img/command_my_timeoff.png +0 -0
- data/img/command_recap.png +0 -0
- data/img/command_repl1.png +0 -0
- data/img/command_repl2.png +0 -0
- data/img/command_ruby.png +0 -0
- data/img/command_run_repl.png +0 -0
- data/img/command_see_announcements.png +0 -0
- data/img/command_see_statuses.png +0 -0
- data/img/command_see_team.png +0 -0
- data/img/command_summarize.png +0 -0
- data/img/commands_inline.png +0 -0
- data/img/commands_on_demand.png +0 -0
- data/img/commands_on_external_call.png +0 -0
- data/img/image_editing.png +0 -0
- data/img/image_generation.png +0 -0
- data/img/image_variations.png +0 -0
- data/img/openai-300.png +0 -0
- data/img/openai.png +0 -0
- data/img/slack-300.png +0 -0
- data/img/slack.png +0 -0
- data/img/smart-bot-150.png +0 -0
- data/img/smart-bot-profile-pic-2.png +0 -0
- data/img/smart-bot-profile-pic.png +0 -0
- data/img/smart-bot.png +0 -0
- data/img/whisper.png +0 -0
- data/lib/slack/smart-bot/ai/open_ai/connect.rb +165 -43
- data/lib/slack/smart-bot/ai/open_ai/models.rb +61 -9
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +67 -11
- data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +4 -3
- data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +4 -4
- data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +4 -3
- data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +4 -3
- data/lib/slack/smart-bot/comm/ask.rb +20 -8
- data/lib/slack/smart-bot/comm/dont_understand.rb +2 -2
- data/lib/slack/smart-bot/comm/event_hello.rb +30 -1
- data/lib/slack/smart-bot/comm/get_channel_members.rb +2 -1
- data/lib/slack/smart-bot/comm/get_presence.rb +1 -0
- data/lib/slack/smart-bot/comm/get_smartbot_team_info.rb +10 -0
- data/lib/slack/smart-bot/comm/get_user_info.rb +45 -6
- data/lib/slack/smart-bot/comm/get_users.rb +8 -1
- data/lib/slack/smart-bot/comm/respond.rb +225 -196
- data/lib/slack/smart-bot/comm/send_msg_channel.rb +2 -2
- data/lib/slack/smart-bot/comm/send_msg_user.rb +10 -9
- data/lib/slack/smart-bot/comm/unreact.rb +2 -2
- data/lib/slack/smart-bot/comm.rb +1 -0
- data/lib/slack/smart-bot/commands/general/add_admin.rb +16 -6
- data/lib/slack/smart-bot/commands/general/add_announcement.rb +3 -3
- data/lib/slack/smart-bot/commands/general/add_vacation.rb +28 -12
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +272 -23
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +42 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +89 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +45 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +41 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +81 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +52 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +52 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +14 -11
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +15 -11
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +29 -17
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +16 -13
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +13 -7
- data/lib/slack/smart-bot/commands/general/allow_access.rb +8 -4
- data/lib/slack/smart-bot/commands/general/bot_help.rb +24 -10
- data/lib/slack/smart-bot/commands/general/bye_bot.rb +9 -5
- data/lib/slack/smart-bot/commands/general/delete_announcement.rb +2 -1
- data/lib/slack/smart-bot/commands/general/delete_share.rb +2 -1
- data/lib/slack/smart-bot/commands/general/deny_access.rb +1 -1
- data/lib/slack/smart-bot/commands/general/get_smartbot_readme.rb +15 -0
- data/lib/slack/smart-bot/commands/general/hi_bot.rb +10 -4
- data/lib/slack/smart-bot/commands/general/personal_settings.rb +26 -8
- data/lib/slack/smart-bot/commands/general/poster.rb +26 -2
- data/lib/slack/smart-bot/commands/general/public_holidays.rb +14 -24
- data/lib/slack/smart-bot/commands/general/recap.rb +399 -0
- data/lib/slack/smart-bot/commands/general/remove_admin.rb +19 -9
- data/lib/slack/smart-bot/commands/general/remove_vacation.rb +23 -6
- data/lib/slack/smart-bot/commands/general/see_access.rb +2 -1
- data/lib/slack/smart-bot/commands/general/see_admins.rb +8 -4
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +5 -5
- data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +4 -4
- data/lib/slack/smart-bot/commands/general/see_shares.rb +1 -1
- data/lib/slack/smart-bot/commands/general/see_vacations.rb +34 -17
- data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +4 -2
- data/lib/slack/smart-bot/commands/general/share_messages.rb +3 -3
- data/lib/slack/smart-bot/commands/general/summarize.rb +191 -0
- data/lib/slack/smart-bot/commands/general/teams/add_team.rb +4 -8
- data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +3 -3
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +34 -29
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +1 -1
- data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +6 -4
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +26 -15
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +33 -24
- data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +4 -4
- data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +10 -8
- data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +73 -61
- data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +28 -13
- data/lib/slack/smart-bot/commands/general/teams/update_team.rb +9 -9
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +1152 -839
- data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +18 -17
- data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +11 -9
- data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +2 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +1 -0
- data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +5 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/delete_message.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +7 -6
- data/lib/slack/smart-bot/commands/on_bot/admin_master/update_message.rb +2 -3
- data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +21 -20
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +40 -7
- data/lib/slack/smart-bot/commands/on_bot/general/bot_status.rb +6 -2
- data/lib/slack/smart-bot/commands/on_bot/general/stop_using_rules.rb +7 -6
- data/lib/slack/smart-bot/commands/on_bot/general/suggest_command.rb +5 -4
- data/lib/slack/smart-bot/commands/on_bot/general/use_rules.rb +4 -3
- data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +4 -4
- data/lib/slack/smart-bot/commands/on_bot/kill_repl.rb +1 -1
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +109 -53
- data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +35 -29
- data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +5 -5
- data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +1 -2
- data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +5 -4
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +22 -12
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +12 -7
- data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +2 -2
- data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +1 -1
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +5 -5
- data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +5 -5
- data/lib/slack/smart-bot/commands/on_master/create_bot.rb +3 -3
- data/lib/slack/smart-bot/commands.rb +10 -0
- data/lib/slack/smart-bot/config.rb +126 -0
- data/lib/slack/smart-bot/listen.rb +12 -11
- data/lib/slack/smart-bot/process.rb +62 -55
- data/lib/slack/smart-bot/process_first.rb +106 -65
- data/lib/slack/smart-bot/treat_message.rb +79 -47
- data/lib/slack/smart-bot/utils/answer.rb +11 -3
- data/lib/slack/smart-bot/utils/answer_delete.rb +11 -3
- data/lib/slack/smart-bot/utils/check_vacations.rb +21 -3
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +13 -13
- data/lib/slack/smart-bot/utils/display_calendar.rb +42 -8
- data/lib/slack/smart-bot/utils/encryption/decrypt.rb +16 -9
- data/lib/slack/smart-bot/utils/encryption/encrypt.rb +14 -11
- data/lib/slack/smart-bot/utils/find_user.rb +71 -0
- data/lib/slack/smart-bot/utils/get_access_channels.rb +22 -3
- data/lib/slack/smart-bot/utils/get_channels_name_and_id.rb +3 -4
- data/lib/slack/smart-bot/utils/get_command_ids.rb +5 -5
- data/lib/slack/smart-bot/utils/get_countries_candelarific.rb +18 -0
- data/lib/slack/smart-bot/utils/get_help.rb +21 -19
- data/lib/slack/smart-bot/utils/get_openai_sessions.rb +47 -0
- data/lib/slack/smart-bot/utils/get_personal_settings.rb +29 -3
- data/lib/slack/smart-bot/utils/get_rules_imported.rb +27 -6
- data/lib/slack/smart-bot/utils/get_shares.rb +1 -1
- data/lib/slack/smart-bot/utils/get_team_members.rb +4 -4
- data/lib/slack/smart-bot/utils/get_vacations.rb +15 -7
- data/lib/slack/smart-bot/utils/has_access.rb +10 -4
- data/lib/slack/smart-bot/utils/is_admin.rb +25 -17
- data/lib/slack/smart-bot/utils/local_time.rb +29 -0
- data/lib/slack/smart-bot/utils/save_stats.rb +5 -3
- data/lib/slack/smart-bot/utils/update_access_channels.rb +19 -3
- data/lib/slack/smart-bot/utils/update_openai_sessions.rb +42 -0
- data/lib/slack/smart-bot/utils/update_personal_settings.rb +11 -3
- data/lib/slack/smart-bot/utils/update_rules_imported.rb +18 -3
- data/lib/slack/smart-bot/utils/update_vacations.rb +5 -2
- data/lib/slack/smart-bot/utils/upgrade_to_use_team_ids.rb +276 -0
- data/lib/slack/smart-bot/utils.rb +6 -1
- data/lib/slack-smart-bot.rb +182 -76
- data/lib/slack-smart-bot_general_commands.rb +10 -9
- data/whats_new.txt +30 -13
- metadata +148 -20
data/lib/slack-smart-bot.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
SP_COMPARE_NUMBERS_AS_STRINGS = false #nice_hash
|
2
|
+
|
1
3
|
require "slack-ruby-client"
|
2
4
|
require "async"
|
3
5
|
require "open-uri"
|
@@ -8,9 +10,12 @@ require "fileutils"
|
|
8
10
|
require "open3"
|
9
11
|
require "nice_http"
|
10
12
|
require "nice_hash"
|
11
|
-
require
|
12
|
-
require
|
13
|
+
require "cgi"
|
14
|
+
require "yaml"
|
15
|
+
require "nokogiri"
|
16
|
+
require 'tiktoken_ruby'
|
13
17
|
|
18
|
+
require_relative "slack/smart-bot/config"
|
14
19
|
require_relative "slack/smart-bot/comm"
|
15
20
|
require_relative "slack/smart-bot/listen"
|
16
21
|
require_relative "slack/smart-bot/treat_message"
|
@@ -21,8 +26,9 @@ require_relative "slack/smart-bot/utils"
|
|
21
26
|
require_relative "slack/smart-bot/ai"
|
22
27
|
|
23
28
|
ADMIN_USERS = MASTER_USERS if defined?(MASTER_USERS) # for bg compatibility
|
29
|
+
|
24
30
|
class SlackSmartBot
|
25
|
-
attr_accessor :config, :client, :client_user
|
31
|
+
attr_accessor :config, :client, :client_user, :client_granular
|
26
32
|
attr_reader :master_bot_id, :channel_id
|
27
33
|
geml = Gem.loaded_specs.values.select { |x| x.name == "slack-smart-bot" }[0]
|
28
34
|
if geml.nil?
|
@@ -31,47 +37,33 @@ class SlackSmartBot
|
|
31
37
|
version = geml.version.to_s
|
32
38
|
end
|
33
39
|
VERSION = version
|
40
|
+
TIMEOUT_LISTENING = 60 * 30 # 30 minutes
|
34
41
|
|
42
|
+
# Initializes the Slack Smart Bot with the given configuration.
|
43
|
+
# Check the README for more information on the configuration options.
|
44
|
+
# and lib/slack/smart-bot/config.rb for the default values.
|
35
45
|
def initialize(config)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
config_defaults = SlackSmartBot::Config.new()
|
47
|
+
abort "The config supplied is not correct. You need to supply a hash with the correct keys and values. The keys are: #{config_defaults.to_h.keys.join(", ")}" unless config.is_a?(Hash)
|
48
|
+
# when simulate true for testing purposes: client, web_client, nick, nick_id, git
|
49
|
+
config_check = config.deep_copy
|
50
|
+
[:client, :web_client, :nick, :nick_id, :git, :allow_access, :authorizations].each do |key|
|
51
|
+
config_check.delete(key)
|
40
52
|
end
|
41
|
-
|
42
|
-
config
|
43
|
-
|
44
|
-
config
|
45
|
-
|
46
|
-
config[
|
47
|
-
config[:
|
48
|
-
config[:
|
49
|
-
config[:
|
50
|
-
|
51
|
-
config
|
52
|
-
|
53
|
-
config[:jira] = { host: '', user: '', password: '' } unless config.key?(:jira) and config[:jira].key?(:host) and config[:jira].key?(:user) and config[:jira].key?(:password)
|
54
|
-
config[:jira][:host] = "https://#{config[:jira][:host]}" unless config[:jira][:host] == '' or config[:jira][:host].match?(/^http/)
|
55
|
-
config[:github] = {token: '' } unless config.key?(:github) and config[:github].key?(:token)
|
56
|
-
config[:github][:host] ||= "https://api.github.com"
|
57
|
-
config[:github][:host] = "https://#{config[:github][:host]}" unless config[:github][:host] == '' or config[:github][:host].match?(/^http/)
|
58
|
-
config[:public_holidays] = { api_key: '' } unless config.key?(:public_holidays) and config[:public_holidays].key?(:api_key)
|
59
|
-
config[:public_holidays][:host] ||= "https://calendarific.com"
|
60
|
-
config[:public_holidays][:host] = "https://#{config[:public_holidays][:host]}" unless config[:public_holidays][:host] == '' or config[:public_holidays][:host].match?(/^http/)
|
61
|
-
config[:encrypt] ||= true unless config.key?(:encrypt)
|
62
|
-
config[:ai] ||= {} unless config.key?(:ai)
|
63
|
-
config[:ai][:open_ai] ||= {
|
64
|
-
access_token: '',
|
65
|
-
organization_id: ''
|
66
|
-
} unless config[:ai].key?(:open_ai)
|
67
|
-
config[:ai][:open_ai][:whisper_model] ||= 'whisper-1'
|
68
|
-
config[:ai][:open_ai][:image_size] ||= '256x256'
|
69
|
-
config[:ai][:open_ai][:gpt_model] ||= 'gpt-3.5-turbo'
|
70
|
-
|
71
|
-
if config.path.to_s!='' and config.file.to_s==''
|
53
|
+
result_config = NiceHash.compare_structure(config_check, config_defaults.to_h)
|
54
|
+
abort "The config supplied is not correct. You need to supply a hash with the correct keys and values. The keys are: #{config_defaults.to_h.keys.join(", ")}" unless result_config
|
55
|
+
|
56
|
+
config = config_defaults.to_h.nice_merge(config)
|
57
|
+
|
58
|
+
config.path.chop! if config.path[-1] == "/"
|
59
|
+
config[:jira][:host] = "https://#{config[:jira][:host]}" unless config[:jira][:host] == "" or config[:jira][:host].match?(/^http/)
|
60
|
+
config[:github][:host] = "https://#{config[:github][:host]}" unless config[:github][:host] == "" or config[:github][:host].match?(/^http/)
|
61
|
+
config[:public_holidays][:host] = "https://#{config[:public_holidays][:host]}" unless config[:public_holidays][:host] == "" or config[:public_holidays][:host].match?(/^http/)
|
62
|
+
|
63
|
+
if config.path.to_s != "" and config.file.to_s == ""
|
72
64
|
config.file = File.basename($0)
|
73
65
|
end
|
74
|
-
if config.key?(:file) and config.file!=
|
66
|
+
if config.key?(:file) and config.file != ""
|
75
67
|
config.file_path = "#{config.path}/#{config.file}"
|
76
68
|
else
|
77
69
|
config.file_path = $0
|
@@ -91,28 +83,63 @@ class SlackSmartBot
|
|
91
83
|
Dir.mkdir("#{config.path}/vacations") unless Dir.exist?("#{config.path}/vacations")
|
92
84
|
Dir.mkdir("#{config.path}/teams") unless Dir.exist?("#{config.path}/teams")
|
93
85
|
Dir.mkdir("#{config.path}/personal_settings") unless Dir.exist?("#{config.path}/personal_settings")
|
86
|
+
Dir.mkdir("#{config.path}/openai") unless Dir.exist?("#{config.path}/openai")
|
87
|
+
|
94
88
|
File.delete("#{config.path}/config_tmp.status") if File.exist?("#{config.path}/config_tmp.status")
|
95
89
|
|
96
|
-
|
97
|
-
|
90
|
+
if !config.simulate
|
91
|
+
if (!config.key?(:token) or config.token.to_s == "")
|
92
|
+
abort "You need to supply a valid token key on the settings. key: :token"
|
93
|
+
elsif (!config.key?(:user_token) or config.user_token.to_s == "")
|
94
|
+
abort "You need to supply a valid user_token key on the settings. key: :user_token"
|
95
|
+
elsif (!config.key?(:granular_token) or config.granular_token.to_s == "")
|
96
|
+
abort "You need to supply a valid granular_token key on the settings. key: :granular_token"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
resp = get_smartbot_team_info(config[:token])
|
101
|
+
if resp.key?(:team) and resp[:team].key?(:enterprise_id)
|
102
|
+
config.team_id = resp[:team][:enterprise_id]
|
103
|
+
else
|
104
|
+
config.team_id = resp.team.id
|
105
|
+
end
|
98
106
|
|
99
|
-
|
100
|
-
|
101
|
-
|
107
|
+
config.masters = MASTER_USERS if config.masters.to_s == "" and defined?(MASTER_USERS)
|
108
|
+
config.team_id_masters ||= []
|
109
|
+
config.team_id_admins ||= []
|
110
|
+
|
111
|
+
config.master_channel = MASTER_CHANNEL if config.master_channel.to_s == "" and defined?(MASTER_CHANNEL)
|
112
|
+
|
113
|
+
if ARGV.size == 0 or (config.file.to_s != "" and config.file.to_s != File.basename($0))
|
114
|
+
config.rules_file = "#{config.file.gsub(".rb", "_rules.rb")}" unless config.rules_file.to_s != ""
|
115
|
+
unless File.exist?(config.path + "/" + config.rules_file)
|
102
116
|
default_rules = (__FILE__).gsub(/\.rb$/, "_rules.rb")
|
103
|
-
FileUtils.copy_file(default_rules, config.path +
|
117
|
+
FileUtils.copy_file(default_rules, config.path + "/" + config.rules_file)
|
104
118
|
end
|
105
|
-
config.admins = config.masters.dup unless config.admins.
|
106
|
-
config.
|
107
|
-
config.
|
119
|
+
config.admins = config.masters.dup unless !config.admins.empty?
|
120
|
+
config.team_id_admins = config.team_id_masters.dup unless !config.team_id_admins.empty?
|
121
|
+
config.channel = config.master_channel unless config.channel.to_s != ""
|
122
|
+
config.status_init = :on unless config.status_init.to_s != ""
|
108
123
|
else
|
109
124
|
config.rules_file = ARGV[2]
|
110
125
|
config.admins = ARGV[1].split(",")
|
111
126
|
config.channel = ARGV[0]
|
112
127
|
config.status_init = ARGV[3].to_sym
|
113
128
|
end
|
114
|
-
config.
|
115
|
-
|
129
|
+
if config.team_id_admins.size != config.admins.size and !config.admins.empty?
|
130
|
+
config.admins.each do |name|
|
131
|
+
if name.match?(/^[A-Z0-9]{7,11}_/)
|
132
|
+
config.team_id_admins << name
|
133
|
+
else
|
134
|
+
config.team_id_admins << "#{config.team_id}_#{name}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
config.team_id_admins.uniq!
|
139
|
+
config.admins.uniq!
|
140
|
+
|
141
|
+
config.rules_file[0] = "" if config.rules_file[0] == "."
|
142
|
+
config.rules_file = "/" + config.rules_file if config.rules_file[0] != "/"
|
116
143
|
|
117
144
|
config.shortcuts_file = "slack-smart-bot_shortcuts_#{config.channel}.yaml".gsub(" ", "_")
|
118
145
|
if config.channel == config.master_channel
|
@@ -122,32 +149,47 @@ class SlackSmartBot
|
|
122
149
|
config.on_master_bot = false
|
123
150
|
end
|
124
151
|
|
125
|
-
if (!config.
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
152
|
+
if (!config.masters.is_a?(Array) or !config.team_id_masters.is_a?(Array)) or
|
153
|
+
(config.masters + config.team_id_masters).empty?
|
154
|
+
message = "You need to supply a masters array on the settings containing the user names of the master admins, for example: [peter]. key: :masters"
|
155
|
+
message += " or a team_id_masters array containing the team_id and user names of the master admins, for example: [TJDFJKD34_peter]. key: :team_id_masters"
|
156
|
+
abort message
|
157
|
+
elsif !config.key?(:master_channel) or config.master_channel.to_s == ""
|
130
158
|
abort "You need to supply a master_channel on the settings. key: :master_channel"
|
131
|
-
elsif !config.key?(:channel) or config.channel.to_s ==
|
159
|
+
elsif !config.key?(:channel) or config.channel.to_s == ""
|
132
160
|
abort "You need to supply a bot channel name on the settings. key: :channel"
|
133
161
|
end
|
134
162
|
|
135
|
-
|
136
|
-
|
137
163
|
logfile = File.basename(config.rules_file.gsub("_rules_", "_logs_"), ".rb") + ".log"
|
138
164
|
config.log_file = logfile
|
139
165
|
@logger = Logger.new("#{config.path}/logs/#{logfile}")
|
140
166
|
@last_respond = Time.now
|
141
|
-
|
142
|
-
|
167
|
+
|
168
|
+
#todo: consider putting this on a method
|
169
|
+
config_log = config.deep_copy
|
143
170
|
config_log.delete(:token)
|
144
171
|
config_log.delete(:user_token)
|
145
|
-
|
172
|
+
config_log.delete(:granular_token)
|
173
|
+
config_log.delete(:authorizations)
|
174
|
+
config_log.jira.password = "********" if config_log.key?(:jira) and config_log.jira.key?(:password)
|
175
|
+
config_log.github.token = "********" if config_log.key?(:github) and config_log.github.key?(:token)
|
176
|
+
config_log.public_holidays.api_key = "********" if config_log.key?(:public_holidays) and config_log.public_holidays.key?(:api_key)
|
177
|
+
config_log.encryption[:key] = "********" if config_log.key?(:encryption) and config_log.encryption[:key].to_s != ""
|
178
|
+
config_log.encryption.iv = "********" if config_log.key?(:encryption) and config_log.encryption.iv.to_s != ""
|
179
|
+
config_log.ai.open_ai.access_token = "********" if config_log.key?(:ai) and config_log.ai.key?(:open_ai) and config_log.ai.open_ai.key?(:access_token)
|
180
|
+
config_log.ai.open_ai.chat_gpt.access_token = "********" if config_log.key?(:ai) and config_log.ai.key?(:open_ai) and config_log.ai.open_ai.key?(:chat_gpt) and config_log.ai.open_ai.chat_gpt.key?(:access_token)
|
181
|
+
config_log.ai.open_ai.dall_e.access_token = "********" if config_log.key?(:ai) and config_log.ai.key?(:open_ai) and config_log.ai.open_ai.key?(:dall_e) and config_log.ai.open_ai.dall_e.key?(:access_token)
|
182
|
+
config_log.ai.open_ai.whisper.access_token = "********" if config_log.key?(:ai) and config_log.ai.key?(:open_ai) and config_log.ai.open_ai.key?(:whisper) and config_log.ai.open_ai.whisper.key?(:access_token)
|
183
|
+
config_log.ai.open_ai.models.access_token = "********" if config_log.key?(:ai) and config_log.ai.key?(:open_ai) and config_log.ai.open_ai.key?(:models) and config_log.ai.open_ai.models.key?(:access_token)
|
184
|
+
config_log.ldap.auth.password = "********" if config_log.key?(:ldap) and config_log.ldap.key?(:auth) and config_log.ldap.auth.key?(:password)
|
185
|
+
@config_log = config_log.deep_copy
|
186
|
+
@logger.info "Initializing bot: #{@config_log.inspect}"
|
146
187
|
|
147
188
|
File.new("#{config.path}/buffer.log", "w") if config[:testing] and config.on_master_bot
|
148
189
|
File.new("#{config.path}/buffer_complete.log", "w") if config[:simulate] and config.on_master_bot
|
149
190
|
|
150
191
|
self.config = config
|
192
|
+
|
151
193
|
save_status :off, :initializing, "Initializing bot: #{config_log.inspect}"
|
152
194
|
|
153
195
|
unless config.simulate and config.key?(:client)
|
@@ -163,10 +205,26 @@ class SlackSmartBot
|
|
163
205
|
@logger.fatal "*" * 50
|
164
206
|
@logger.fatal "Rescued on creation client_user: #{e.inspect}"
|
165
207
|
self.client_user = nil
|
208
|
+
abort "Rescued on creation client_user. You need to supply a valid user_token key on the settings. key: :user_token.\n#{e.inspect}"
|
166
209
|
end
|
167
210
|
else
|
168
211
|
self.client_user = nil
|
169
212
|
end
|
213
|
+
|
214
|
+
unless (config.simulate and config.key?(:client)) or config.granular_token.nil? or config.granular_token.empty?
|
215
|
+
begin
|
216
|
+
self.client_granular = Slack::Web::Client.new(token: config.granular_token)
|
217
|
+
self.client_granular.auth_test
|
218
|
+
rescue Exception => e
|
219
|
+
@logger.fatal "*" * 50
|
220
|
+
@logger.fatal "Rescued on creation client_granular: #{e.inspect}"
|
221
|
+
self.client_granular = nil
|
222
|
+
abort "Rescued on creation client_granular. You need to supply a valid granular_token key on the settings. key: :granular_token.\n#{e.inspect}"
|
223
|
+
end
|
224
|
+
else
|
225
|
+
self.client_granular = nil
|
226
|
+
end
|
227
|
+
|
170
228
|
restarts = 0
|
171
229
|
created = false
|
172
230
|
while restarts < 200 and !created
|
@@ -202,7 +260,25 @@ class SlackSmartBot
|
|
202
260
|
end
|
203
261
|
end
|
204
262
|
|
263
|
+
if config.team_id_masters.empty?
|
264
|
+
config.masters.each_with_index do |name, i|
|
265
|
+
if name.match?(/^[A-Z0-9]{7,11}_/)
|
266
|
+
config.team_id_masters << name
|
267
|
+
config.masters[i] = name.split("_")[1..-1].join("_")
|
268
|
+
else
|
269
|
+
config.team_id_masters << "#{config.team_id}_#{name}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
else
|
273
|
+
config.masters = []
|
274
|
+
config.team_id_masters.each_with_index do |tid_name, i|
|
275
|
+
name = tid_name.split("_")[1..-1].join("_")
|
276
|
+
config.masters << name
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
205
280
|
@listening = Hash.new()
|
281
|
+
@listening[:threads] = Hash.new() #[thread_ts] => channel_id
|
206
282
|
|
207
283
|
@bots_created = Hash.new()
|
208
284
|
@shortcuts = Hash.new()
|
@@ -217,30 +293,57 @@ class SlackSmartBot
|
|
217
293
|
@announcements = Hash.new()
|
218
294
|
@shares = Hash.new()
|
219
295
|
@last_status_change = Time.now
|
220
|
-
@vacations_check = (
|
296
|
+
@vacations_check = (Time.now - 3600).strftime("%Y%m%d%H")
|
221
297
|
@announcements_activity_after = Hash.new()
|
222
298
|
@public_holidays = Hash.new()
|
223
299
|
@loops = Hash.new()
|
300
|
+
@ai_gpt ||= {}
|
301
|
+
@active_chat_gpt_sessions = Hash.new()
|
302
|
+
@chat_gpt_collaborating = Hash.new()
|
303
|
+
@open_ai = Hash.new()
|
304
|
+
@open_ai_models = []
|
305
|
+
@slack_bots = Hash.new()
|
306
|
+
|
307
|
+
@ldap = nil
|
308
|
+
begin
|
309
|
+
if config.ldap.key?(:host) and config.ldap[:host].to_s != ""
|
310
|
+
require 'net/ldap'
|
311
|
+
if config.ldap.key?(:auth) and config.ldap[:auth].key?(:user) and config.ldap[:auth][:user].to_s != ""
|
312
|
+
@ldap = Net::LDAP.new(host: config.ldap.host, port: config.ldap.port, auth: config.ldap.auth)
|
313
|
+
else
|
314
|
+
@ldap = Net::LDAP.new(host: config.ldap.host, port: config.ldap.port)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
rescue Exception => e
|
318
|
+
@logger.fatal "Rescued on creation ldap: #{e.inspect}"
|
319
|
+
@ldap = nil
|
320
|
+
end
|
321
|
+
|
322
|
+
if (config.on_master_bot and !File.exist?("#{config.path}/status/version.txt")) or
|
323
|
+
(config.on_master_bot and File.exist?("#{config.path}/status/version.txt") and
|
324
|
+
Gem::Version.new(File.read("#{config.path}/status/version.txt").to_s) <= Gem::Version.new("1.15.0"))
|
325
|
+
upgrade_to_use_team_ids()
|
326
|
+
end
|
224
327
|
|
225
|
-
if File.exist?("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(
|
226
|
-
file_conf = IO.readlines("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(
|
328
|
+
if File.exist?("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(".yaml", ".rb")) #backwards compatible
|
329
|
+
file_conf = IO.readlines("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(".yaml", ".rb")).join
|
227
330
|
if file_conf.to_s() == ""
|
228
331
|
@shortcuts = {}
|
229
332
|
else
|
230
333
|
@shortcuts = eval(file_conf)
|
231
334
|
end
|
232
|
-
File.open("#{config.path}/shortcuts/#{config.shortcuts_file}",
|
233
|
-
File.delete("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(
|
335
|
+
File.open("#{config.path}/shortcuts/#{config.shortcuts_file}", "w") { |file| file.write(@shortcuts.to_yaml) }
|
336
|
+
File.delete("#{config.path}/shortcuts/#{config.shortcuts_file}".gsub(".yaml", ".rb"))
|
234
337
|
elsif File.exist?("#{config.path}/shortcuts/#{config.shortcuts_file}")
|
235
338
|
@shortcuts = YAML.load(File.read("#{config.path}/shortcuts/#{config.shortcuts_file}"))
|
236
339
|
end
|
237
|
-
if File.exist?("#{config.path}/shortcuts/shortcuts_global.rb")
|
340
|
+
if File.exist?("#{config.path}/shortcuts/shortcuts_global.rb") #backwards compatible
|
238
341
|
file_sc = IO.readlines("#{config.path}/shortcuts/shortcuts_global.rb").join
|
239
342
|
@shortcuts_global = {}
|
240
343
|
unless file_sc.to_s() == ""
|
241
344
|
@shortcuts_global = eval(file_sc)
|
242
345
|
end
|
243
|
-
File.open("#{config.path}/shortcuts/shortcuts_global.yaml",
|
346
|
+
File.open("#{config.path}/shortcuts/shortcuts_global.yaml", "w") { |file| file.write(@shortcuts_global.to_yaml) }
|
244
347
|
File.delete("#{config.path}/shortcuts/shortcuts_global.rb")
|
245
348
|
elsif File.exist?("#{config.path}/shortcuts/shortcuts_global.yaml")
|
246
349
|
@shortcuts_global = YAML.load(File.read("#{config.path}/shortcuts/shortcuts_global.yaml"))
|
@@ -249,12 +352,12 @@ class SlackSmartBot
|
|
249
352
|
get_routines()
|
250
353
|
get_repls()
|
251
354
|
|
252
|
-
if config.on_master_bot and (File.exist?(config.file_path.gsub(".rb", "_bots.rb")) or File.exist?(config.file_path.gsub(
|
355
|
+
if config.on_master_bot and (File.exist?(config.file_path.gsub(".rb", "_bots.rb")) or File.exist?(config.file_path.gsub(".rb", "_bots.yaml")))
|
253
356
|
get_bots_created()
|
254
357
|
if @bots_created.kind_of?(Hash) and config.start_bots
|
255
358
|
@bots_created.each { |key, value|
|
256
359
|
if !value.key?(:cloud) or (value.key?(:cloud) and value[:cloud] == false)
|
257
|
-
if value.key?(:silent) and value.silent!=config.silent
|
360
|
+
if value.key?(:silent) and value.silent != config.silent
|
258
361
|
silent = value.silent
|
259
362
|
else
|
260
363
|
silent = config.silent
|
@@ -280,24 +383,26 @@ class SlackSmartBot
|
|
280
383
|
FileUtils.copy_file(default_general_commands, config.path + general_commands_file) unless File.exist?(config.path + general_commands_file)
|
281
384
|
|
282
385
|
get_rules_imported()
|
283
|
-
|
284
386
|
begin
|
285
387
|
#todo: take in consideration the case that the value supplied on config.masters and config.admins are the ids and not the user names
|
286
388
|
@admin_users_id = []
|
287
389
|
@master_admin_users_id = []
|
288
|
-
config.
|
390
|
+
config.team_id_admins.each do |au|
|
289
391
|
user_info = get_user_info("@#{au}")
|
290
392
|
@admin_users_id << user_info.user.id
|
291
|
-
if config.
|
393
|
+
if config.team_id_masters.include?(au)
|
292
394
|
@master_admin_users_id << user_info.user.id
|
293
395
|
end
|
294
396
|
sleep 1
|
295
397
|
end
|
296
|
-
(config.
|
398
|
+
(config.team_id_masters - config.team_id_admins).each do |au|
|
297
399
|
user_info = get_user_info("@#{au}")
|
298
|
-
@master_admin_users_id << user_info.user.id
|
400
|
+
@master_admin_users_id << user_info.user.id unless user_info.nil?
|
299
401
|
sleep 1
|
300
402
|
end
|
403
|
+
@admin_users_id.uniq!
|
404
|
+
@master_admin_users_id.uniq!
|
405
|
+
|
301
406
|
rescue Slack::Web::Api::Errors::TooManyRequestsError
|
302
407
|
@logger.fatal "TooManyRequestsError"
|
303
408
|
save_status :off, :TooManyRequestsError, "TooManyRequestsError please re run the bot and be sure of executing first: killall ruby"
|
@@ -337,6 +442,7 @@ class SlackSmartBot
|
|
337
442
|
get_admins_channels()
|
338
443
|
get_access_channels()
|
339
444
|
get_vacations()
|
445
|
+
get_openai_sessions()
|
340
446
|
get_personal_settings()
|
341
447
|
|
342
448
|
if @routines.key?(@channel_id)
|
@@ -361,7 +467,7 @@ class SlackSmartBot
|
|
361
467
|
@logger.info _data
|
362
468
|
#save_status :off, :closing, "Connection closing, exiting." #todo: don't notify for the moment, remove when checked
|
363
469
|
end
|
364
|
-
|
470
|
+
|
365
471
|
client.on :closed do |_data|
|
366
472
|
m = "Connection has been disconnected. #{Time.now}"
|
367
473
|
@logger.info m
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# add here the general commands you will be using in any channel where The SmartBot is part of. Not necessary to use ! or ^, it will answer directly.
|
2
2
|
def general_commands(user, command, dest, files = [])
|
3
|
-
|
3
|
+
|
4
4
|
begin
|
5
|
+
team_id_user = "#{user.team_id}_#{user.name}"
|
5
6
|
case command
|
6
7
|
|
7
8
|
# help: ----------------------------------------------
|
@@ -12,7 +13,7 @@ def general_commands(user, command, dest, files = [])
|
|
12
13
|
# help: It will send a big empty message.
|
13
14
|
# help: NUMBER (optional): number of lines. Default 100. Max 200.
|
14
15
|
# help: command_id: :cls
|
15
|
-
# help:
|
16
|
+
# help:
|
16
17
|
when /\A\s*(\d*)\s*(clear|cls|clear\s+screen)\s*\z/i
|
17
18
|
save_stats :cls
|
18
19
|
$1.to_s == '' ? lines = 100 : lines = $1.to_i
|
@@ -24,12 +25,12 @@ def general_commands(user, command, dest, files = [])
|
|
24
25
|
# help: `INTEGER blink TEXT`
|
25
26
|
# help: It will blink the text supplied. One or more lines of text. Emoticons or text format are allowed.
|
26
27
|
# help: INTEGER (optional): number of times. Default 50. Max 200.
|
27
|
-
# help: Examples:
|
28
|
+
# help: Examples:
|
28
29
|
# help: blink Hello World!
|
29
30
|
# help: blink :moneybag: Pay attention! *Sales* are published!
|
30
31
|
# help: 100 blink :new: *Party is about to start* :i_love_you_hand_sign:
|
31
32
|
# help: command_id: :blink
|
32
|
-
# help:
|
33
|
+
# help:
|
33
34
|
when /\A\s*(\d+)?\s*blink\s+(.+)\s*\z/im
|
34
35
|
save_stats :blink
|
35
36
|
num_times = $1.to_s == '' ? 50 : $1.to_i
|
@@ -37,12 +38,12 @@ def general_commands(user, command, dest, files = [])
|
|
37
38
|
@blinking ||= []
|
38
39
|
if num_times > 200 or num_times < 1
|
39
40
|
respond "The number of times must be between 1 and 200"
|
40
|
-
elsif @blinking.include?(
|
41
|
+
elsif @blinking.include?(team_id_user)
|
41
42
|
respond "I'm already blinking something for you. Please wait until I finish"
|
42
43
|
elsif @blinking.size >= 3 # rate limit in theory update can be done only once per second
|
43
44
|
respond "I'm already blinking something for too many people. Please wait until I finish at least one of them."
|
44
45
|
else
|
45
|
-
@blinking <<
|
46
|
+
@blinking << team_id_user
|
46
47
|
msg = respond(text, return_message: true)
|
47
48
|
num_times.times do
|
48
49
|
sleep 2
|
@@ -50,7 +51,7 @@ def general_commands(user, command, dest, files = [])
|
|
50
51
|
sleep 0.5
|
51
52
|
update(dest, msg.ts, text)
|
52
53
|
end
|
53
|
-
@blinking.delete(
|
54
|
+
@blinking.delete(team_id_user)
|
54
55
|
end
|
55
56
|
|
56
57
|
# this is a hidden command that it is not listed when calling bot help
|
@@ -58,7 +59,7 @@ def general_commands(user, command, dest, files = [])
|
|
58
59
|
save_stats :thanks
|
59
60
|
reactions = [:heart, :heart_eyes, :blush, :relaxed, :simple_smile, :smiley, :two_hearts, :heartbeat, :green_heart ]
|
60
61
|
reactions.sample(rand(3)+1).each {|rt| react rt }
|
61
|
-
responses = ['Thank YOU', "You're welcome", "You're very welcome", 'No problem', 'No worries', "Don't mention it", 'My pleasure',
|
62
|
+
responses = ['Thank YOU', "You're welcome", "You're very welcome", 'No problem', 'No worries', "Don't mention it", 'My pleasure',
|
62
63
|
'Anytime', 'It was the least I could do', 'Glad to help', 'Sure', 'Pleasure', 'The pleasure is mine', 'It was nothing', 'Much obliged', "I'm happy to help",
|
63
64
|
'Það var ekkert', 'De nada', 'No hay de qué', 'De rien', 'Bitte', 'Prego', 'मेरा सौभाग्य है', '不客氣', 'Παρακαλώ']
|
64
65
|
respond "#{responses.sample}#{'!'*rand(4)}"
|
@@ -91,4 +92,4 @@ def general_commands(user, command, dest, files = [])
|
|
91
92
|
end
|
92
93
|
return false
|
93
94
|
end
|
94
|
-
end
|
95
|
+
end
|
data/whats_new.txt
CHANGED
@@ -1,20 +1,37 @@
|
|
1
|
-
*Version 1.
|
1
|
+
*Version 1.15.0* Released 2024-Apr-04
|
2
2
|
|
3
3
|
*For General users*
|
4
|
-
-
|
5
|
-
-
|
6
|
-
-
|
7
|
-
-
|
8
|
-
-
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
4
|
+
- OpenAI adds specific hosts and access tokens for services. (<https://github.com/MarioRuiz/slack-smart-bot/issues/107|#107>).
|
5
|
+
- ChatGPT command improvements. (<https://github.com/MarioRuiz/slack-smart-bot/issues/108|#108>)
|
6
|
+
- ChatGPT sharing sessions. (<https://github.com/MarioRuiz/slack-smart-bot/issues/110|#110>)
|
7
|
+
- ChatGPT tags for sessions. (<https://github.com/MarioRuiz/slack-smart-bot/issues/111|#111>)
|
8
|
+
- ChatGPT can be called inside a REPL to help you create scripts. (<https://github.com/MarioRuiz/slack-smart-bot/issues/112|#112>)
|
9
|
+
- ChatGPT has access to internet. If a prompt includes `!URL`, SmartBot will download the supplied website text and add it to the prompt. (<https://github.com/MarioRuiz/slack-smart-bot/issues/113|#113>)
|
10
|
+
- ChatGPT deletes all prompts from the session when on a Thread and sending `??` (<https://github.com/MarioRuiz/slack-smart-bot/issues/115|#115>)
|
11
|
+
- ChatGPT to use a different model when starting a temporary session: `^?? use model MODEL_NAME` (<https://github.com/MarioRuiz/slack-smart-bot/issues/114|#114>)
|
12
|
+
- ChatGPT when on a session if we want to change the model send `use model MODEL_NAME` (<https://github.com/MarioRuiz/slack-smart-bot/issues/114|#114>)
|
13
|
+
- ChatGPT To send the results of a SmartBot command as input for a ChatGPT session, use `COMMAND ?? PROMPT`. Example: `bot help ?? how can I use the time off commands`. (<https://github.com/MarioRuiz/slack-smart-bot/issues/116|#116>)
|
14
|
+
- ChatGPT To copy the prompts from the temporary session: `chatgpt copy temporary session NEW_SESSION_NAME` (<https://github.com/MarioRuiz/slack-smart-bot/issues/125|#125>)
|
15
|
+
- Time Off shows the day of today differently from other days. (<https://github.com/MarioRuiz/slack-smart-bot/issues/118|#118>)
|
16
|
+
- Teams It is possible to filter by topic, for example: `sales team dev` (<https://github.com/MarioRuiz/slack-smart-bot/issues/118|#124>)
|
17
|
+
- All users in the channel will be able to use SmartBot even though they are not workspace members. (<https://github.com/MarioRuiz/slack-smart-bot/issues/123|#123>)
|
18
|
+
- SmartBot can be called from Slack Workflows or Slack apps (<https://github.com/MarioRuiz/slack-smart-bot/issues/122|#122>)
|
19
|
+
- New `recap` command. It will show a recap of the channel. If channel not supplied, it will show the recap of the current channel (<https://github.com/MarioRuiz/slack-smart-bot/issues/126|#126>)
|
20
|
+
- New `summarize` command. It will summarize using ChatGPT the messages in the channel since the date specified (<https://github.com/MarioRuiz/slack-smart-bot/issues/127|#127>)
|
21
|
+
- Call `get smartbot readme` to get the README for SmartBot. (<https://github.com/MarioRuiz/slack-smart-bot/issues/128|#128>)
|
22
|
+
- You can call `<bot help` or `<bot rules`. SmartBot will send a Markdown file with extended help commands. Open the file in a new window. You can install this extension in Google Chrome to view it: https://chromewebstore.google.com/detail/medapdbncneneejhbgcjceippjlfkmkg (<https://github.com/MarioRuiz/slack-smart-bot/issues/129|#129>)
|
23
|
+
- It is possible to specify authorizations tokens for any website you want to reach the content using ChatGPT command. When adding to your prompt !URL SmartBot will verify if the domain specified have set an authorization header and add it. To add personal authorization tokens you can do it calling on a DM the commands: `add personal settings authorizations.example.host example.com`, `add personal settings authorizations.example.authorization Xdddj33a_SDFBBBS33Ab` (<https://github.com/MarioRuiz/slack-smart-bot/issues/130|#130>)
|
12
24
|
|
13
25
|
*For Admin users*
|
14
|
-
-
|
15
|
-
-
|
16
|
-
-
|
26
|
+
- ChatGPT now supports Azure. (<https://github.com/MarioRuiz/slack-smart-bot/issues/109|#109>)
|
27
|
+
- Bot Stats will store also the team of the user.
|
28
|
+
- Added granular_token to SmartBot settings. Supply the Slack token of your granular App.
|
29
|
+
- New config added to lib/slack/smart-bot/config.rb
|
30
|
+
- It is possible now to use LLM proxy for ChatGPT and also specify a concrete end point to get the models.
|
31
|
+
- Added LDAP settings in config. (<https://github.com/MarioRuiz/slack-smart-bot/issues/131|#131>)
|
32
|
+
- Added authorizations settings in config. (<https://github.com/MarioRuiz/slack-smart-bot/issues/130|#130>)
|
17
33
|
|
18
34
|
------------------------------
|
19
35
|
|
20
|
-
*Previous*: <https://github.com/MarioRuiz/slack-smart-bot/blob/
|
36
|
+
*Previous*: <https://github.com/MarioRuiz/slack-smart-bot/blob/3a4b369d6d32316690e873309eb0758511a2c513/whats_new.txt|1.14.2>
|
37
|
+
|