slack-smart-bot 1.15.0 → 1.15.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +34 -1
- data/img/chat_gpt_attach_image.png +0 -0
- data/lib/slack/smart-bot/ai/open_ai/models.rb +19 -10
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +14 -10
- data/lib/slack/smart-bot/comm/dont_understand.rb +23 -6
- data/lib/slack/smart-bot/comm/get_user_info.rb +9 -10
- data/lib/slack/smart-bot/comm/respond.rb +56 -28
- data/lib/slack/smart-bot/comm/send_file.rb +17 -6
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +885 -129
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_add_collaborator.rb +3 -3
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_copy_session.rb +132 -15
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_delete_session.rb +1 -1
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_get_prompts.rb +50 -12
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_list_sessions.rb +99 -34
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_share_session.rb +12 -2
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat_use_model.rb +36 -25
- data/lib/slack/smart-bot/commands/general/bot_help.rb +29 -24
- data/lib/slack/smart-bot/commands/general/poster.rb +0 -1
- data/lib/slack/smart-bot/commands/general/see_announcements.rb +1 -1
- data/lib/slack/smart-bot/commands/general/summarize.rb +22 -8
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +156 -55
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +13 -11
- data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +21 -17
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +2 -2
- data/lib/slack/smart-bot/commands.rb +19 -19
- data/lib/slack/smart-bot/process_first.rb +38 -35
- data/lib/slack/smart-bot/treat_message.rb +57 -56
- data/lib/slack/smart-bot/utils/download_http_content.rb +91 -0
- data/lib/slack/smart-bot/utils/get_authorizations.rb +41 -0
- data/lib/slack/smart-bot/utils/get_keywords.rb +33 -0
- data/lib/slack/smart-bot/utils/get_openai_sessions.rb +46 -6
- data/lib/slack/smart-bot/utils/get_teams.rb +9 -1
- data/lib/slack/smart-bot/utils/save_stats.rb +13 -5
- data/lib/slack/smart-bot/utils/transform_to_slack_markdown.rb +36 -0
- data/lib/slack/smart-bot/utils/update_openai_sessions.rb +9 -4
- data/lib/slack/smart-bot/utils.rb +48 -44
- data/lib/slack-smart-bot.rb +10 -10
- data/whats_new.txt +27 -1
- metadata +49 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eae826f4dd78e2f74b1ce77cb89b8e2c42282bb242db0d42b469dfe8dac9c502
|
4
|
+
data.tar.gz: d9d7b750d738c58f37f9df9c0be19feee22aedb1c93c904e5b0e3f21b8b56c90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67e0ded851f65cdb368471b3b016e4da58c9e4d82dda0a4d7fb3d796079b5adc62021cd69f3e0f88b4dc8847e6248d3a95ea4de236628fb43242ac3bb438cb81
|
7
|
+
data.tar.gz: c804e0884ab1505b2024c2f7819060f2e149e3174dc2527fb65ac5e0f1a14e0ef6139021f6efc6e475385802a9bcf40d3c55ee76135c437571302274d7b31e0d
|
data/README.md
CHANGED
@@ -44,6 +44,8 @@ slack-smart-bot has the ability to create bots on demand, set up shortcuts, exec
|
|
44
44
|
* [OpenAI](#openai)
|
45
45
|
+ [OpenAI Set up](#openai-setup) (A)
|
46
46
|
+ [Chat GPT](#chatgpt)
|
47
|
+
+ [Docs Folder for ChatGPT Sessions](#docs-folder-for-chatgpt-sessions) (A)
|
48
|
+
+ [Restrict who has access to a specific model](#restrict-who-has-access-to-a-specific-model) (A)
|
47
49
|
+ [Image Generation](#image-generation)
|
48
50
|
+ [Image Variations](#image-variations)
|
49
51
|
+ [Image Editing](#image-editing)
|
@@ -859,7 +861,20 @@ To get all prompts from a specific session name use `chatGPT get SESSION_NAME`.
|
|
859
861
|
To list all sessions you created use `chatGPT sessions`.
|
860
862
|
When starting a new session, if you ask SmartBot to answer on a Thread by using !! or ^, then it won't be necessary to send ? before the prompt. In this case, every single message you send will be considered a prompt to be treated. After 30 minutes of inactivity, SmartBot will stop listening to the thread. You will need to continue the session after that. If you want to avoid a message to be treated then start it with a hyphen '-'.
|
861
863
|
To add a collaborator when on a thread, you can use directly `add collaborator @USER`
|
862
|
-
If you include in the prompt `!URL` then it will download and use the content of the URL as input for the prompt.
|
864
|
+
If you include in the prompt `!URL` then it will download and use the content of the URL as input for the prompt. If the URL is a Google Drive link, it will download the content of the file. PDF, DOCX and text files (txt, json, yaml...) are supported.
|
865
|
+
If you want to add static content to your session to be used: `add static content URL1 URL99`.
|
866
|
+
Add live content to your session by using `add live content URL1 URL99`. The content will be downloaded and added to your session every time you send a new prompt.
|
867
|
+
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`
|
868
|
+
Also you can add authorizations on a specific ChatGPT session: `add authorization HOST HEADER VALUE`, for example: `add authorization api.example.com Authorization Bearer 123456`. If you share this session as public or for a specific channel, users will be able to send prompts for that session using your authorizations but they won't be able to see the auth values or copy those auth to a new chatgpt session.
|
869
|
+
You can add messages from a channel to your session by using `add history #CHANNEL_NAME`.
|
870
|
+
|
871
|
+
If you want to delete the last ChatGPT response and send again last prompt, you can use `resend prompt`.
|
872
|
+
You can set the context of your ChatGPT session: `set context CONTEXT`. Example: `set context You are a funny comedian who tells dad jokes. The output should be in JSON format.`
|
873
|
+
|
874
|
+
Also if you are using a model that allows you to add images to your prompt (fex gpt-4o), you can attach any images.
|
875
|
+
|
876
|
+
<img src="img/chat_gpt_attach_image.png" width="500">
|
877
|
+
|
863
878
|
When on a thread you can change the model to be used by sending `use model MODEL_NAME`. For a temporary session if you want to create the session with a specific model use `?? use model MODEL_NAME`. The model supplied can be a substring of the model name, SmartBot will try to find the model that matches the substring.
|
864
879
|
|
865
880
|
<img src="img/chat_gpt_session.png" width="650">
|
@@ -873,9 +888,27 @@ To remove any shared session from the list, call `chatGPT stop sharing SESSION_N
|
|
873
888
|
Play this video:
|
874
889
|
[![SmartBot ChatGPT Share Sessions](https://img.youtube.com/vi/Mnve3tnEd-8/0.jpg)](https://www.youtube.com/watch?v=Mnve3tnEd-8)
|
875
890
|
|
891
|
+
It is possible to use a session that is public, private or shared with a channel as a temporary session: `?? use SESSION_NAME PROMPT`. For example: `?? use lunch What's for Thursday?`. This will create a temporary session using the session named as `lunch` and send the prompt `What's for Thursday?`
|
892
|
+
|
876
893
|
You can also use ChatGPT when creating REPLs. During the REPL session you can ask *ChatGPT* about the code or any other question. Just start the message with `?` and the Smart Bot will ask ChatGPT and will post the answer. Example: `? How to create a new customer?`. If you send just the question mark without a prompt then ChatGPT will suggest next code line. Example: `?`
|
877
894
|
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`. If you are on a thread you can send more SmartBot commands to the same session by using `COMMAND ?? PROMPT`.
|
878
895
|
|
896
|
+
##### Docs Folder for ChatGPT Sessions
|
897
|
+
> For admins
|
898
|
+
|
899
|
+
Doc folders can be added by admins for specific chatgpt sessions. SmartBot will filter those docs depending on the prompt and attach them along with the prompt.
|
900
|
+
Put all docs as text files on `./openai/TEAM_ID/USER_NAME/SESSION_NAME/docs_folder`.
|
901
|
+
For the documents to be filtered add them to `filter` subfolder under `docs_folder`.
|
902
|
+
For the documents to be added always to the prompts, add them to `include` subfolder under `docs_folder`.
|
903
|
+
Inside those subfolders you can organize the documents the way you want.
|
904
|
+
|
905
|
+
##### Restrict who has access to a specific model
|
906
|
+
> For admins
|
907
|
+
|
908
|
+
You can add a file named restricted_models.yaml on ./openai folder supplying the models and users that will have access to specific models.
|
909
|
+
Example of content:
|
910
|
+
o1-mini: [rmario, peter]
|
911
|
+
o1-preview: [rmario]
|
879
912
|
|
880
913
|
#### Image Generation
|
881
914
|
> for all users
|
Binary file
|
@@ -1,26 +1,35 @@
|
|
1
1
|
class SlackSmartBot
|
2
2
|
module AI
|
3
3
|
module OpenAI
|
4
|
-
def self.models(open_ai_client, models_config, model=
|
4
|
+
def self.models(open_ai_client, models_config, model = "", return_response: false)
|
5
5
|
require "openai"
|
6
|
-
require
|
6
|
+
require "amazing_print"
|
7
7
|
user = Thread.current[:user]
|
8
|
-
|
8
|
+
models = []
|
9
|
+
if model.empty? or model == "chatgpt"
|
9
10
|
if open_ai_client.is_a?(NiceHttp) and models_config.url != ""
|
10
11
|
resp = open_ai_client.get(models_config.url)
|
11
|
-
|
12
|
-
|
12
|
+
#save resp to a file
|
13
|
+
resp.body.json.data.each do |m|
|
14
|
+
if model.empty? or (model == "chatgpt" and
|
15
|
+
(m[:model_name].to_s.include?("gpt-") or (m.key?(:model_info) and m[:model_info][:mode].to_s == "chat")))
|
16
|
+
models << m[:model_name]
|
17
|
+
end
|
18
|
+
end
|
13
19
|
elsif open_ai_client.is_a?(NiceHttp) #azure
|
20
|
+
#todo: consider filtering by model mode
|
14
21
|
resp = open_ai_client.get("/openai/deployments?api-version=#{models_config.api_version}")
|
15
22
|
models = resp.body.json(:id)
|
16
|
-
models.
|
23
|
+
models.flatten!
|
24
|
+
models.select! { |i| i.include?("gpt-") } if model == "chatgpt"
|
17
25
|
else
|
26
|
+
#todo: consider filtering by model mode
|
18
27
|
response = open_ai_client.models.list
|
19
28
|
models = []
|
20
29
|
response.data.each do |model|
|
21
30
|
models << model["id"]
|
22
31
|
end
|
23
|
-
models.select!{|i| i.include?(
|
32
|
+
models.select! { |i| i.include?("gpt-") } if model == "chatgpt"
|
24
33
|
end
|
25
34
|
if return_response
|
26
35
|
return models.uniq.sort
|
@@ -39,11 +48,11 @@ class SlackSmartBot
|
|
39
48
|
end
|
40
49
|
end
|
41
50
|
if result.empty?
|
42
|
-
response = {message: "Model not found"}
|
51
|
+
response = { message: "Model not found" }
|
43
52
|
response_obj = response
|
44
53
|
else
|
45
|
-
response = {message:
|
46
|
-
result[:model_info].each do |k,v|
|
54
|
+
response = { message: "" }
|
55
|
+
result[:model_info].each do |k, v|
|
47
56
|
response.message += "#{k}: #{v}\n"
|
48
57
|
end
|
49
58
|
response_obj = result[:model_info]
|
@@ -1,43 +1,47 @@
|
|
1
1
|
class SlackSmartBot
|
2
2
|
module AI
|
3
3
|
module OpenAI
|
4
|
-
def self.send_gpt_chat(open_ai_client, model,
|
4
|
+
def self.send_gpt_chat(open_ai_client, model, messages, chat_gpt_config)
|
5
5
|
require "openai"
|
6
|
-
require
|
6
|
+
require "nice_http"
|
7
7
|
user = Thread.current[:user]
|
8
8
|
if user.key?(:sso_user_name)
|
9
9
|
user_name = user.sso_user_name
|
10
10
|
else
|
11
11
|
user_name = user.name
|
12
12
|
end
|
13
|
+
if messages.is_a?(String)
|
14
|
+
messages = [{ role: "user", content: messages }]
|
15
|
+
end
|
13
16
|
parameters = {
|
14
17
|
model: model, # Required.
|
15
|
-
messages:
|
18
|
+
messages: messages,
|
16
19
|
temperature: 0.7,
|
17
|
-
user: user_name
|
20
|
+
user: user_name,
|
18
21
|
}
|
22
|
+
|
19
23
|
parameters.user = chat_gpt_config.fixed_user if chat_gpt_config.fixed_user.to_s != ""
|
20
24
|
if open_ai_client.is_a?(NiceHttp)
|
21
25
|
begin
|
22
26
|
response = {}
|
23
27
|
tries = 0
|
24
|
-
while (!response.key?(:data) or response.data.nil? or response.data.empty?
|
28
|
+
while (!response.key?(:data) or response.data.nil? or response.data.empty?) and tries < 10
|
25
29
|
begin
|
26
30
|
request = {
|
27
31
|
path: "/openai/deployments/#{model}/chat/completions?api-version=#{chat_gpt_config.api_version}",
|
28
|
-
data: parameters
|
32
|
+
data: parameters,
|
29
33
|
}
|
30
34
|
response = open_ai_client.post(request)
|
31
35
|
rescue Exception => exception
|
32
|
-
response = {message: exception.message}.to_json
|
36
|
+
response = { message: exception.message }.to_json
|
33
37
|
end
|
34
38
|
tries += 1
|
35
39
|
sleep 1 if !response.key?(:data) or response.data.nil? or response.data.empty? #wait a second before trying again
|
36
40
|
end
|
37
|
-
response.data = { message: ""}.to_json if !response.key?(:data) or response.data.nil? or response.data.empty?
|
41
|
+
response.data = { message: "" }.to_json if !response.key?(:data) or response.data.nil? or response.data.empty?
|
38
42
|
response = response.data
|
39
43
|
rescue Exception => exception
|
40
|
-
response = {message: exception.message}.to_json
|
44
|
+
response = { message: exception.message }.to_json
|
41
45
|
end
|
42
46
|
else
|
43
47
|
begin
|
@@ -49,7 +53,7 @@ class SlackSmartBot
|
|
49
53
|
response.body.error.message += "\nThe user on Slack is: #{user.name}\nYou have to go to your Profile Slack Account on a browser. Then go to Settings.\nNow go to Username and click on expand, change the name to your SSO name and click on Save"
|
50
54
|
end
|
51
55
|
if response.nil?
|
52
|
-
response = {message: e.message}
|
56
|
+
response = { message: e.message }
|
53
57
|
else
|
54
58
|
response = response.to_json
|
55
59
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
|
3
2
|
def dont_understand(rules_file = nil, command = nil, user = nil, dest = nil, answer = ["what?", "huh?", "sorry?", "what do you mean?", "I don't understand"], channel_rules: config.channel, typem: nil)
|
4
3
|
save_stats(:dont_understand)
|
5
4
|
command = Thread.current[:command] if command.nil?
|
@@ -7,10 +6,10 @@ class SlackSmartBot
|
|
7
6
|
dest = Thread.current[:dest] if dest.nil?
|
8
7
|
rules_file = Thread.current[:rules_file] if rules_file.nil?
|
9
8
|
typem = Thread.current[:typem] if typem.nil?
|
10
|
-
if typem
|
9
|
+
if typem == :on_extended
|
11
10
|
get_bots_created()
|
12
11
|
end
|
13
|
-
text = get_help(rules_file, dest, user, typem
|
12
|
+
text = get_help(rules_file, dest, user, typem == :on_extended, true)
|
14
13
|
|
15
14
|
ff = text.scan(/^\s*`\s*([^`]+)\s*`\s*$/i).flatten
|
16
15
|
ff.delete("!THE_COMMAND")
|
@@ -41,7 +40,7 @@ class SlackSmartBot
|
|
41
40
|
end
|
42
41
|
res_final.flatten!
|
43
42
|
|
44
|
-
if typem
|
43
|
+
if typem == :on_extended
|
45
44
|
if @extended_from[@channels_name[dest]].size == 1
|
46
45
|
respond "#{user.profile.display_name}, I don't understand.", dest
|
47
46
|
end
|
@@ -49,8 +48,8 @@ class SlackSmartBot
|
|
49
48
|
respond "Similar rules on : *#{channel_rules}*\n`#{res_final[0..4].join("`\n`")}`", dest
|
50
49
|
end
|
51
50
|
else
|
52
|
-
message =
|
53
|
-
message = "\nTake in consideration when on external calls, not all the commands are available." if typem
|
51
|
+
message = ""
|
52
|
+
message = "\nTake in consideration when on external calls, not all the commands are available." if typem == :on_call
|
54
53
|
if res_final.empty?
|
55
54
|
resp = answer.sample
|
56
55
|
respond "#{user.profile.display_name}, #{resp}#{message}", dest
|
@@ -58,5 +57,23 @@ class SlackSmartBot
|
|
58
57
|
respond "#{user.profile.display_name}, I don't understand. Maybe you are trying to say:\n`#{res_final[0..4].join("`\n`")}`#{message}", dest
|
59
58
|
end
|
60
59
|
end
|
60
|
+
|
61
|
+
ai_conn, message = SlackSmartBot::AI::OpenAI.connect({}, config, {}, service: :chat_gpt)
|
62
|
+
if message.empty?
|
63
|
+
react :speech_balloon
|
64
|
+
chatgpt = ai_conn[Thread.current[:team_id_user]].chat_gpt
|
65
|
+
model = chatgpt.smartbot_model if model.nil?
|
66
|
+
prompt = "I sent this command to Slack SmartBot: `#{command}` and it seems that is wrong\n\n"
|
67
|
+
prompt += "These are the available SmartBot commands:\n#{text}\n\n"
|
68
|
+
prompt += "Please, can you suggest the command that I mean?\n"
|
69
|
+
prompt += "Return just like 5 lines of text max. If you supply a command do it like this: `the command`"
|
70
|
+
success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(chatgpt.client, model, prompt, chatgpt)
|
71
|
+
if success
|
72
|
+
response_message = "*ChatGPT*: Maybe you are trying to say:\n#{res.to_s.strip}\n\n"
|
73
|
+
response_message += "Remember you can always ask for help by calling `bot help ?? YOUR QUESTION`."
|
74
|
+
respond transform_to_slack_markdown(response_message), dest
|
75
|
+
end
|
76
|
+
unreact :speech_balloon
|
77
|
+
end
|
61
78
|
end
|
62
79
|
end
|
@@ -1,17 +1,16 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
|
3
2
|
def get_user_info(user, is_bot: false)
|
4
3
|
begin
|
5
|
-
if user.to_s.length>0
|
6
|
-
if user[0]==
|
4
|
+
if user.to_s.length > 0
|
5
|
+
if user[0] == "@" #name
|
7
6
|
user = user[1..-1]
|
8
7
|
is_name = true
|
9
8
|
else
|
10
9
|
is_name = false
|
11
10
|
end
|
12
11
|
if user.match?(/^[A-Z0-9]{7,11}_/) #team_id_user_name
|
13
|
-
team_id = user.split(
|
14
|
-
user = user.split(
|
12
|
+
team_id = user.split("_")[0]
|
13
|
+
user = user.split("_")[1..-1].join("_")
|
15
14
|
else
|
16
15
|
team_id = config.team_id
|
17
16
|
end
|
@@ -19,20 +18,20 @@ class SlackSmartBot
|
|
19
18
|
if client.web_client.users_info.key?(user.to_sym) #id
|
20
19
|
client.web_client.users_info[user.to_sym]
|
21
20
|
else #name
|
22
|
-
client.web_client.users_info.select{|k, v| v[:user][:name] == user and v[:user][:team_id] == team_id}.values[-1]
|
21
|
+
client.web_client.users_info.select { |k, v| v[:user][:name] == user and v[:user][:team_id] == team_id }.values[-1]
|
23
22
|
end
|
24
23
|
else
|
25
24
|
if is_bot
|
26
25
|
@logger.info "Getting bot info for <#{user}>"
|
27
26
|
begin
|
28
27
|
result = client.web_client.bots_info(bot: user)
|
29
|
-
rescue Exception =>
|
30
|
-
@logger.warn
|
28
|
+
rescue Exception => e
|
29
|
+
@logger.warn "Failed to get bot info for <#{user}>: #{e.message}"
|
31
30
|
return nil
|
32
31
|
end
|
33
32
|
if !result.nil? and result.key?(:bot) and result[:bot].key?(:user_id)
|
34
|
-
|
35
|
-
|
33
|
+
user = result[:bot][:user_id]
|
34
|
+
is_name = false
|
36
35
|
else
|
37
36
|
return nil
|
38
37
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
def respond(msg = "", dest = nil, unfurl_links: true, unfurl_media: true, thread_ts: "", web_client: true, blocks: [], dont_share: false, return_message: false, max_chars_per_message: 4000)
|
2
|
+
def respond(msg = "", dest = nil, unfurl_links: true, unfurl_media: true, thread_ts: "", web_client: true, blocks: [], dont_share: false, return_message: false, max_chars_per_message: 4000, split: true)
|
3
3
|
result = true
|
4
4
|
resp = nil
|
5
5
|
|
@@ -10,7 +10,7 @@ class SlackSmartBot
|
|
10
10
|
if (msg.to_s != "" or !msg.to_s.match?(/^A\s*\z/) or !blocks.empty?) and Thread.current[:routine_type].to_s != "bgroutine"
|
11
11
|
if !web_client.is_a?(TrueClass) and !web_client.is_a?(FalseClass)
|
12
12
|
(!unfurl_links or !unfurl_media) ? web_client = true : web_client = false
|
13
|
-
end
|
13
|
+
end
|
14
14
|
begin
|
15
15
|
msg = msg.to_s
|
16
16
|
web_client = true if !blocks.empty?
|
@@ -38,7 +38,7 @@ class SlackSmartBot
|
|
38
38
|
|
39
39
|
dest = @channels_id[dest] if @channels_id.key?(dest) #it is a name of channel
|
40
40
|
|
41
|
-
on_thread ? txt_on_thread=":on_thread:" : txt_on_thread=
|
41
|
+
on_thread ? txt_on_thread = ":on_thread:" : txt_on_thread = ""
|
42
42
|
|
43
43
|
if blocks.empty?
|
44
44
|
if !config.simulate #https://api.slack.com/docs/rate-limits
|
@@ -62,36 +62,40 @@ class SlackSmartBot
|
|
62
62
|
num_chars_code = 0
|
63
63
|
print_previous = false
|
64
64
|
if in_a_code_block
|
65
|
-
all_lines[i+1..-1].each do |l|
|
66
|
-
num_chars_code += l.size
|
65
|
+
all_lines[i + 1..-1].each do |l|
|
66
|
+
num_chars_code += l.size + 1 # +1 for the \n
|
67
67
|
break if l.match?(/^\s*```/)
|
68
68
|
end
|
69
|
-
if num_chars_code + (m + txt).size > max_chars_per_message
|
69
|
+
if (num_chars_code + (m + txt).size > max_chars_per_message) and txt != ""
|
70
70
|
print_previous = true
|
71
|
-
end
|
71
|
+
end
|
72
72
|
end
|
73
|
-
end
|
73
|
+
end
|
74
74
|
if ((m + txt).size > max_chars_per_message and !in_a_code_block) or print_previous
|
75
75
|
unless txt == ""
|
76
|
-
txt[0] =
|
76
|
+
txt[0] = "." if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
|
77
77
|
if m.match?(/^\s*```\s*$/) and !in_a_code_block
|
78
78
|
txt += (m + "\n")
|
79
79
|
m = ""
|
80
80
|
end
|
81
|
-
|
82
|
-
|
81
|
+
if split
|
82
|
+
t = txt.chars.each_slice(max_chars_per_message).map(&:join) #jalsplit
|
83
|
+
msgs << t
|
84
|
+
else
|
85
|
+
msgs << txt #not necessary to split the message in smaller parts since we are sending it as a file now
|
86
|
+
end
|
83
87
|
txt = ""
|
84
88
|
print_previous = false if print_previous
|
85
89
|
end
|
86
90
|
end
|
87
91
|
txt += (m + "\n")
|
88
|
-
txt[0] =
|
92
|
+
txt[0] = "." if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char
|
89
93
|
txt[0] = ". " if txt.match?(/\A\t/)
|
90
94
|
end
|
91
95
|
end
|
92
96
|
msgs << txt
|
93
97
|
msgs.flatten!
|
94
|
-
msgs.delete_if{|e| e.match?(/\A\s*\z/)}
|
98
|
+
msgs.delete_if { |e| e.match?(/\A\s*\z/) }
|
95
99
|
if dest.nil?
|
96
100
|
if config[:simulate]
|
97
101
|
open("#{config.path}/buffer_complete.log", "a") { |f|
|
@@ -100,19 +104,27 @@ class SlackSmartBot
|
|
100
104
|
else
|
101
105
|
if on_thread
|
102
106
|
msgs.each do |msg|
|
103
|
-
if
|
104
|
-
resp =
|
107
|
+
if msg.size > max_chars_per_message
|
108
|
+
resp = send_file(@channel_id, "", "", "", "", "text", content: msg)
|
105
109
|
else
|
106
|
-
|
110
|
+
if web_client
|
111
|
+
resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
|
112
|
+
else
|
113
|
+
resp = client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
114
|
+
end
|
107
115
|
end
|
108
116
|
sleep wait
|
109
117
|
end
|
110
118
|
else
|
111
119
|
msgs.each do |msg|
|
112
|
-
if
|
113
|
-
resp =
|
120
|
+
if msg.size > max_chars_per_message
|
121
|
+
resp = send_file(@channel_id, "", "", "", "", "text", content: msg)
|
114
122
|
else
|
115
|
-
|
123
|
+
if web_client
|
124
|
+
resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
125
|
+
else
|
126
|
+
resp = client.message(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
127
|
+
end
|
116
128
|
end
|
117
129
|
sleep wait
|
118
130
|
end
|
@@ -132,19 +144,27 @@ class SlackSmartBot
|
|
132
144
|
else
|
133
145
|
if on_thread
|
134
146
|
msgs.each do |msg|
|
135
|
-
if
|
136
|
-
resp =
|
147
|
+
if msg.size > max_chars_per_message
|
148
|
+
resp = send_file(dest, "", "", "", "", "text", content: msg)
|
137
149
|
else
|
138
|
-
|
150
|
+
if web_client
|
151
|
+
resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
|
152
|
+
else
|
153
|
+
resp = client.message(channel: dest, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
154
|
+
end
|
139
155
|
end
|
140
156
|
sleep wait
|
141
157
|
end
|
142
158
|
else
|
143
159
|
msgs.each do |msg|
|
144
|
-
if
|
145
|
-
resp =
|
160
|
+
if msg.size > max_chars_per_message
|
161
|
+
resp = send_file(dest, "", "", "", "", "text", content: msg)
|
146
162
|
else
|
147
|
-
|
163
|
+
if web_client
|
164
|
+
resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
165
|
+
else
|
166
|
+
resp = client.message(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
167
|
+
end
|
148
168
|
end
|
149
169
|
sleep wait
|
150
170
|
end
|
@@ -158,14 +178,22 @@ class SlackSmartBot
|
|
158
178
|
end
|
159
179
|
elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message
|
160
180
|
msgs.each do |msg|
|
161
|
-
|
181
|
+
if msg.size > max_chars_per_message
|
182
|
+
resp = send_file(dest, "", "", "", "", "text", content: msg)
|
183
|
+
else
|
184
|
+
resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
|
185
|
+
end
|
162
186
|
sleep wait
|
163
187
|
end
|
164
188
|
elsif dest[0] == "@"
|
165
189
|
begin
|
166
190
|
user_info = @users.select { |u| u.id == dest[1..-1] or u.name == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1]
|
167
191
|
msgs.each do |msg|
|
168
|
-
|
192
|
+
if msg.size > max_chars_per_message
|
193
|
+
resp = send_file(user_info.id, "", "", "", "", "text", content: msg)
|
194
|
+
else
|
195
|
+
resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts)
|
196
|
+
end
|
169
197
|
sleep wait
|
170
198
|
end
|
171
199
|
rescue Exception => stack
|
@@ -190,7 +218,7 @@ class SlackSmartBot
|
|
190
218
|
else
|
191
219
|
if on_thread
|
192
220
|
blocks.each_slice(40).to_a.each do |blockstmp|
|
193
|
-
|
221
|
+
resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true, thread_ts: thread_ts)
|
194
222
|
sleep wait
|
195
223
|
end
|
196
224
|
else
|
@@ -5,10 +5,10 @@ class SlackSmartBot
|
|
5
5
|
#send_file(dest, 'the message', "#{project_folder}/temp/example.jpeg", 'message to be sent', 'image/jpeg', "jpg")
|
6
6
|
#send_file(dest, 'the message', "", 'message to be sent', 'text/plain', "ruby", content: "the content to be sent when no file supplied")
|
7
7
|
#send_file(dest, 'the message', "myfile.rb", 'message to be sent', 'text/plain', "ruby", content: "the content to be sent when no file supplied")
|
8
|
-
def send_file(to, msg, file, title, format, type = "text", content:
|
8
|
+
def send_file(to, msg, file, title, format, type = "text", content: "")
|
9
9
|
unless config[:simulate]
|
10
10
|
begin
|
11
|
-
file =
|
11
|
+
file = "myfile" if file.to_s == "" and content != ""
|
12
12
|
if to[0] == "U" or to[0] == "W" #user
|
13
13
|
im = client.web_client.conversations_open(users: id_user)
|
14
14
|
channel = im["channel"]["id"]
|
@@ -22,7 +22,7 @@ class SlackSmartBot
|
|
22
22
|
ts = nil
|
23
23
|
end
|
24
24
|
|
25
|
-
if content.to_s ==
|
25
|
+
if content.to_s == ""
|
26
26
|
client.web_client.files_upload(
|
27
27
|
channels: channel,
|
28
28
|
as_user: true,
|
@@ -31,9 +31,21 @@ class SlackSmartBot
|
|
31
31
|
filename: file,
|
32
32
|
filetype: type,
|
33
33
|
initial_comment: msg,
|
34
|
-
thread_ts: ts
|
34
|
+
thread_ts: ts,
|
35
35
|
)
|
36
36
|
else
|
37
|
+
content.strip!
|
38
|
+
#if first line is ```TYPE, then set file_type to TYPE
|
39
|
+
if content[0..2] == "```"
|
40
|
+
type = content[3..-1].split("\n")[0]
|
41
|
+
content = content.split("\n")[1..-1].join("\n")
|
42
|
+
#remove the last line if it is ```
|
43
|
+
if content[-3..-1] == "```"
|
44
|
+
content = content[0..-4]
|
45
|
+
end
|
46
|
+
content.gsub!(/[\u0080-\uFFFF]/, "?") #replace all non-ascii characters with a question mark
|
47
|
+
end
|
48
|
+
type = "text" if type.to_s == ""
|
37
49
|
client.web_client.files_upload(
|
38
50
|
channels: channel,
|
39
51
|
as_user: true,
|
@@ -42,7 +54,7 @@ class SlackSmartBot
|
|
42
54
|
filename: file,
|
43
55
|
filetype: type,
|
44
56
|
initial_comment: msg,
|
45
|
-
thread_ts: ts
|
57
|
+
thread_ts: ts,
|
46
58
|
)
|
47
59
|
end
|
48
60
|
rescue Exception => stack
|
@@ -50,5 +62,4 @@ class SlackSmartBot
|
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
53
|
-
|
54
65
|
end
|