slack-smart-bot 1.13.1 → 1.14.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 +100 -4
- data/lib/slack/smart-bot/ai/open_ai/connect.rb +61 -0
- data/lib/slack/smart-bot/ai/open_ai/models.rb +21 -0
- data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +24 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +23 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +18 -0
- data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +22 -0
- data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +21 -0
- data/lib/slack/smart-bot/ai.rb +8 -0
- data/lib/slack/smart-bot/comm/get_channel_members.rb +15 -13
- data/lib/slack/smart-bot/comm/get_channels.rb +31 -29
- data/lib/slack/smart-bot/comm/respond_thread.rb +2 -2
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +40 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +66 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +65 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +37 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +84 -0
- data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +51 -0
- data/lib/slack/smart-bot/commands/general/bot_help.rb +1 -0
- data/lib/slack/smart-bot/commands/general/personal_settings.rb +38 -0
- data/lib/slack/smart-bot/commands/general/poster.rb +107 -104
- data/lib/slack/smart-bot/commands/general/public_holidays.rb +116 -114
- data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +6 -2
- data/lib/slack/smart-bot/commands/general/teams/add_team.rb +87 -0
- data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +69 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +136 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +37 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +83 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +97 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +304 -0
- data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +66 -0
- data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +104 -0
- data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +236 -0
- data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +183 -0
- data/lib/slack/smart-bot/commands/general/teams/update_team.rb +137 -0
- data/lib/slack/smart-bot/commands/general_bot_commands.rb +905 -741
- data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +379 -353
- data/lib/slack/smart-bot/commands/on_bot/repl.rb +87 -189
- data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +233 -0
- data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +17 -4
- data/lib/slack/smart-bot/commands.rb +26 -10
- data/lib/slack/smart-bot/process.rb +14 -3
- data/lib/slack/smart-bot/process_first.rb +36 -2
- data/lib/slack/smart-bot/treat_message.rb +28 -0
- data/lib/slack/smart-bot/utils/check_vacations.rb +1 -0
- data/lib/slack/smart-bot/utils/create_routine_thread.rb +1 -1
- data/lib/slack/smart-bot/utils/display_calendar.rb +17 -10
- data/lib/slack/smart-bot/utils/encryption/decrypt.rb +23 -0
- data/lib/slack/smart-bot/utils/encryption/encrypt.rb +27 -0
- data/lib/slack/smart-bot/utils/{encryption_get_key_iv.rb → encryption/encryption_get_key_iv.rb} +12 -8
- data/lib/slack/smart-bot/utils/get_help.rb +3 -1
- data/lib/slack/smart-bot/utils/get_personal_settings.rb +14 -0
- data/lib/slack/smart-bot/utils/get_teams.rb +2 -2
- data/lib/slack/smart-bot/utils/get_vacations.rb +2 -2
- data/lib/slack/smart-bot/utils/save_stats.rb +3 -1
- data/lib/slack/smart-bot/utils/update_personal_settings.rb +18 -0
- data/lib/slack/smart-bot/utils/update_teams.rb +1 -1
- data/lib/slack/smart-bot/utils/update_vacations.rb +1 -1
- data/lib/slack/smart-bot/utils.rb +5 -3
- data/lib/slack-smart-bot.rb +12 -0
- data/whats_new.txt +13 -14
- metadata +63 -15
- data/lib/slack/smart-bot/commands/general/add_memo_team.rb +0 -117
- data/lib/slack/smart-bot/commands/general/add_team.rb +0 -81
- data/lib/slack/smart-bot/commands/general/delete_memo_team.rb +0 -69
- data/lib/slack/smart-bot/commands/general/delete_team.rb +0 -55
- data/lib/slack/smart-bot/commands/general/ping_team.rb +0 -100
- data/lib/slack/smart-bot/commands/general/see_memos_team.rb +0 -202
- data/lib/slack/smart-bot/commands/general/see_teams.rb +0 -230
- data/lib/slack/smart-bot/commands/general/see_vacations_team.rb +0 -136
- data/lib/slack/smart-bot/commands/general/set_memo_status.rb +0 -58
- data/lib/slack/smart-bot/commands/general/update_team.rb +0 -131
- data/lib/slack/smart-bot/utils/decrypt.rb +0 -15
- data/lib/slack/smart-bot/utils/encrypt.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fef5b10f464c14059a0c350c44e0bbb86c7c92db0f60a05516982c79e4764159
|
4
|
+
data.tar.gz: 5fa566a1f3198e1021a5a1f3ae6759e0814eeafa394e7acad2117bf0661d2cfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a73bdd8c22589f205997f00723e15b791805430b4c614f33ea0abe32dee48fc5c6e9f8b7bd0709eb35376e133e40389c12e5efc7e0f5b8f871553cfe9f0b4f3
|
7
|
+
data.tar.gz: a98455b32e704fb57a84c6df1df523f0967a8499bf1c61bbda079f951b9f4b854e65f02395f2b85743e93ef05eb9ac505a57f452af9b0399ea362982392ac9ab
|
data/README.md
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/slack-smart-bot.svg)](https://rubygems.org/gems/slack-smart-bot)
|
4
4
|
[![Build Status](https://travis-ci.com/MarioRuiz/slack-smart-bot.svg?branch=master)](https://github.com/MarioRuiz/slack-smart-bot)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/slack-smart-bot/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/slack-smart-bot?branch=master)
|
6
|
+
![Gem](https://img.shields.io/gem/dt/slack-smart-bot)
|
7
|
+
![GitHub commit activity](https://img.shields.io/github/commit-activity/y/MarioRuiz/slack-smart-bot)
|
8
|
+
![GitHub last commit](https://img.shields.io/github/last-commit/MarioRuiz/slack-smart-bot)
|
9
|
+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/MarioRuiz/slack-smart-bot)
|
6
10
|
|
7
11
|
Create a Slack bot that is really smart and so easy to expand.
|
8
12
|
|
@@ -10,7 +14,7 @@ The main scope of this ruby gem is to be used internally in your company so team
|
|
10
14
|
|
11
15
|
slack-smart-bot can create bots on demand, create shortcuts, run ruby code... just on a chat channel, you can access it just from your mobile phone if you want and run those tests you forgot to run, get the results, restart a server... no limits.
|
12
16
|
|
13
|
-
<img src="
|
17
|
+
<img src="./img/smart-bot.png" width="150" height="150">![](./img/slack.png)
|
14
18
|
|
15
19
|
# Table of Contents
|
16
20
|
|
@@ -36,6 +40,14 @@ slack-smart-bot can create bots on demand, create shortcuts, run ruby code... ju
|
|
36
40
|
* [See favorite commands](#see-favorite-commands)
|
37
41
|
* [Teams](#teams)
|
38
42
|
* [Time off management](#time-off-management)
|
43
|
+
* [OpenAI](#openai)
|
44
|
+
+ [OpenAI Set up](#openai-setup)
|
45
|
+
+ [Chat GPT](#chatgpt)
|
46
|
+
+ [Image Generation](#image-generation)
|
47
|
+
+ [Image Variations](#image-variations)
|
48
|
+
+ [Image Editing](#image-editing)
|
49
|
+
+ [Whisper](#whisper)
|
50
|
+
+ [Models](#models)
|
39
51
|
* [Tips](#tips)
|
40
52
|
+ [Send a file](#send-a-file) (A)
|
41
53
|
+ [Download a file](#download-a-file) (A)
|
@@ -382,9 +394,9 @@ By default it will be automatically loaded the gems: `string_pattern`, `nice_has
|
|
382
394
|
|
383
395
|
To pre-execute some ruby when starting the session add the code to `.smart-bot-repl` file on the project root folder defined on `project_folder`. Then that file will be always executed before the REPL started or created. In that case if we want to avoid to run that file before the REPL we can do it adding the word 'clean' before the command `clean repl`.
|
384
396
|
|
385
|
-
If you want to see the methods of a class or module you created use `ls TheModuleOrClass`
|
397
|
+
If you want to see the methods of a class or module you created use `ls TheModuleOrClass`. To see all documentation of a method: `doc TheModuleOrClass.method_name`. And to see the source code of a method: `code TheModuleOrClass.method_name`. Examples: `ls Sales`, `doc Sales.list`, `code Sales.list`
|
386
398
|
|
387
|
-
You can supply the Environmental Variables you need for the Session
|
399
|
+
You can supply the Environmental Variables you need for the Session
|
388
400
|
|
389
401
|
Examples:
|
390
402
|
_repl CreateCustomer LOCATION=spain HOST='https://10.30.40.50:8887'_
|
@@ -674,6 +686,8 @@ In case of 'github' type then you can supply an URL filtering the Github issues
|
|
674
686
|
|
675
687
|
If you want to change the memo status use the command `set STATUS on memo ID TEAM_NAME team`. For example: `set :runner: on memo 7 Sales team`
|
676
688
|
|
689
|
+
You can add also comments to any memo by calling: `team TEAM_NAME memo ID MESSAGE`. To see a specific memo and all the comments: `team TEAM_NAME memo ID`. In case of a Jira or GitHub memo then it will show also the comments in there.
|
690
|
+
|
677
691
|
Examples:
|
678
692
|
>**_`add memo to sales team : Add tests for Michigan feature`_**
|
679
693
|
>**_`add private note to sales team : Bills will need to be deployed before Friday`_**
|
@@ -686,6 +700,8 @@ Examples:
|
|
686
700
|
>**_`set :runner: on memo 7 team Sales`_**
|
687
701
|
>**_`see all memos from Sales team`_**
|
688
702
|
>**_`see bugs from Sales team dev`_**
|
703
|
+
>**_`sales team memo 4 Put it on hold until tests for Apple feature are finished`_**
|
704
|
+
>**_`sales team memo 7`_**
|
689
705
|
|
690
706
|
Other team commands: **_`delete team TEAM_NAME`_**, **_`delete memo ID from team TEAM_NAME`_**, **_`set STATUS on memo ID TEAM_NAME team`_**, **_`see MEMO_TYPE from TEAM_NAME team TOPIC`_**
|
691
707
|
|
@@ -718,11 +734,91 @@ settings = {
|
|
718
734
|
}
|
719
735
|
```
|
720
736
|
|
721
|
-
When calling `see my time off` on a DM will display a calendar of the year with the days off, including public holidays
|
737
|
+
When calling `see my time off` on a DM will display a calendar of the year with the days off, including public holidays
|
738
|
+
|
722
739
|
<img src="img/my_timeoff.png" width="650">
|
723
740
|
|
724
741
|
Other 'time off' commands: **_`remove time off ID`_**, **_`see my time off`_**, **_`see vacations @USER`_**, **_`time off team NAME`_**, **_`set public holidays to COUNTRY/REGION`_**
|
725
742
|
|
743
|
+
|
744
|
+
### OpenAI
|
745
|
+
> for all users
|
746
|
+
#### OpenAI setup
|
747
|
+
To be able to use this SmartBot general command you need to ask for an API token: https://platform.openai.com/account/api-keys
|
748
|
+
|
749
|
+
Then specify in the SmartBot config the keys:
|
750
|
+
|
751
|
+
```ruby
|
752
|
+
ai: {
|
753
|
+
open_ai: {
|
754
|
+
access_token: 'OPENAI_ACCESS_TOKEN',
|
755
|
+
organization_id: 'OPENAI_ORGANIZATION_ID',
|
756
|
+
gpt_model: 'gpt-3.5-turbo',
|
757
|
+
whisper_model : 'whisper-1',
|
758
|
+
image_size: '256x256'
|
759
|
+
}
|
760
|
+
}
|
761
|
+
```
|
762
|
+
|
763
|
+
Or if you want you can set your personal access token just to be used by you by calling on a DM with the SmartBot the command: `set personal settings ai.open_ai.access_token ACCESS_TOKEN`
|
764
|
+
Also you can specify personal settings for `gpt_model`, `whisper_model` or `image_size`, instead of using the default values.
|
765
|
+
|
766
|
+
#### ChatGPT
|
767
|
+
|
768
|
+
`??`
|
769
|
+
`?? PROMPT`
|
770
|
+
`? PROMPT`
|
771
|
+
Chat GPT will generate a response based on the PROMPT indicated.
|
772
|
+
If ?? is used, it will start from zero the session. If not all the previous prompts from the session will be used to generate the response.
|
773
|
+
You can share a message and use it as input for the supplied prompt.
|
774
|
+
|
775
|
+
<img src="img/chat_gpt.png" width="650">
|
776
|
+
|
777
|
+
<img src="img/chat_gpt_share.png" width="300">
|
778
|
+
|
779
|
+
#### Image Generation
|
780
|
+
`??i PROMPT`
|
781
|
+
`?i PROMPT`
|
782
|
+
`?ir`
|
783
|
+
It will generate an image based on the PROMPT indicated.
|
784
|
+
If `??i` is used, it will start from zero the session. If not all the previous prompts from the session will be used to generate the image.
|
785
|
+
if using `?ir` will generate a new image using the session prompts.
|
786
|
+
|
787
|
+
<img src="img/image_generation.png" width="400">
|
788
|
+
|
789
|
+
#### Image Variations
|
790
|
+
|
791
|
+
`?iv`
|
792
|
+
`?ivNUMBER`
|
793
|
+
It will generate a variation of the last image generated in the session.
|
794
|
+
In the case of NUMBER, it will generate NUMBER of variations of the last image generated. NUMBER needs to be between 1 and 9.
|
795
|
+
If an image is attached then it will generate temporary variations of the attached image.
|
796
|
+
|
797
|
+
<img src="img/image_variations.png" width="400">
|
798
|
+
|
799
|
+
#### Image Editing
|
800
|
+
|
801
|
+
`?ie PROMPT`
|
802
|
+
It will edit the attached image with the supplied PROMPT. The supplied image needs to be an image with a transparent area.
|
803
|
+
The PROMPT need to explain the final result of the image.
|
804
|
+
|
805
|
+
<img src="img/image_editing.png" width="400">
|
806
|
+
|
807
|
+
#### Whisper
|
808
|
+
|
809
|
+
`?w PROMPT`
|
810
|
+
`?w`
|
811
|
+
It will transcribe the audio file attached and perform the PROMPT indicated if supplied.
|
812
|
+
|
813
|
+
<img src="img/whisper.png" width="650">
|
814
|
+
|
815
|
+
#### Models
|
816
|
+
|
817
|
+
`?m`
|
818
|
+
`?m MODEL`
|
819
|
+
It will return the list of models available or the details of the model indicated.
|
820
|
+
|
821
|
+
|
726
822
|
### Tips
|
727
823
|
> for admins
|
728
824
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.connect(ai_open_ai, general_config, personal_settings, reconnect: false)
|
5
|
+
require "openai"
|
6
|
+
user = Thread.current[:user]
|
7
|
+
ai_open_ai = {} if ai_open_ai.nil?
|
8
|
+
|
9
|
+
# ._ai to avoid to call .ai method from amazing_print
|
10
|
+
ai_open_ai[user.name] ||= { client: nil, gpt_model: general_config._ai.open_ai.gpt_model, whisper_model: general_config._ai.open_ai.whisper_model, image_size: general_config._ai.open_ai.image_size }
|
11
|
+
if personal_settings.key?(user.name) and personal_settings[user.name].key?("ai.open_ai.gpt_model") and
|
12
|
+
personal_settings[user.name]["ai.open_ai.gpt_model"] != ""
|
13
|
+
ai_open_ai[user.name][:gpt_model] = personal_settings[user.name]["ai.open_ai.gpt_model"]
|
14
|
+
elsif general_config.key?(:ai) and general_config[:ai].key?(:open_ai) and general_config[:ai][:open_ai].key?(:gpt_model) and
|
15
|
+
general_config[:ai][:open_ai][:gpt_model] != ""
|
16
|
+
ai_open_ai[user.name][:gpt_model] = general_config[:ai][:open_ai][:gpt_model]
|
17
|
+
end
|
18
|
+
if personal_settings.key?(user.name) and personal_settings[user.name].key?("ai.open_ai.whisper_model") and
|
19
|
+
personal_settings[user.name]["ai.open_ai.whisper_model"] != ""
|
20
|
+
ai_open_ai[user.name][:whisper_model] = personal_settings[user.name]["ai.open_ai.whisper_model"]
|
21
|
+
elsif general_config.key?(:ai) and general_config[:ai].key?(:open_ai) and general_config[:ai][:open_ai].key?(:whisper_model) and
|
22
|
+
general_config[:ai][:open_ai][:whisper_model] != ""
|
23
|
+
ai_open_ai[user.name][:whisper_model] = general_config[:ai][:open_ai][:whisper_model]
|
24
|
+
end
|
25
|
+
if personal_settings.key?(user.name) and personal_settings[user.name].key?("ai.open_ai.image_size") and
|
26
|
+
personal_settings[user.name]["ai.open_ai.image_size"] != ""
|
27
|
+
ai_open_ai[user.name][:image_size] = personal_settings[user.name]["ai.open_ai.image_size"]
|
28
|
+
elsif general_config.key?(:ai) and general_config[:ai].key?(:open_ai) and general_config[:ai][:open_ai].key?(:image_size) and
|
29
|
+
general_config[:ai][:open_ai][:image_size] != ""
|
30
|
+
ai_open_ai[user.name][:image_size] = general_config[:ai][:open_ai][:image_size]
|
31
|
+
end
|
32
|
+
if ai_open_ai.key?(user.name) and ai_open_ai[user.name] != nil and ai_open_ai[user.name].key?(:client) and
|
33
|
+
ai_open_ai[user.name][:client] != nil and !reconnect
|
34
|
+
# do nothing
|
35
|
+
elsif personal_settings.key?(user.name) and personal_settings[user.name].key?("ai.open_ai.access_token") and
|
36
|
+
personal_settings[user.name]["ai.open_ai.access_token"].to_s != ""
|
37
|
+
ai_open_ai[user.name].client = ::OpenAI::Client.new(access_token: personal_settings[user.name]["ai.open_ai.access_token"].to_s)
|
38
|
+
elsif general_config.key?(:ai) and general_config[:ai].key?(:open_ai) and general_config[:ai][:open_ai].key?(:access_token) and
|
39
|
+
general_config[:ai][:open_ai][:access_token] != ""
|
40
|
+
ai_open_ai[user.name].client = ::OpenAI::Client.new(access_token: general_config[:ai][:open_ai][:access_token])
|
41
|
+
else
|
42
|
+
ai_open_ai[user.name] = nil
|
43
|
+
message = ["You need to set the OpenAI access token in the config file or in the personal settings."]
|
44
|
+
message << "You can get it from https://platform.openai.com/account/api-keys"
|
45
|
+
message << "Then in case you are a master admin, you can set it in the SmartBot config file:"
|
46
|
+
message << " `ai: { open_ai: { access_token: 'ACCESS_TOKEN'} }`"
|
47
|
+
message << "If you want to use your personal access token, you can set it on a DM with SmartBot in the personal settings:"
|
48
|
+
message << " `set personal settings ai.open_ai.access_token ACCESS_TOKEN`"
|
49
|
+
message << "By default we will be using the gpt_model #{general_config._ai.open_ai.gpt_model}. You can change it in the config file or in personal settings:"
|
50
|
+
message << " `set personal settings ai.open_ai.gpt_model gpt-4`"
|
51
|
+
message << "By default we will be using the whisper_model #{general_config._ai.open_ai.whisper_model}. You can change it in the config file or in personal settings:"
|
52
|
+
message << " `set personal settings ai.open_ai.whisper_model whisper-1`"
|
53
|
+
message << "You can also change the image size in the config file or in personal settings:"
|
54
|
+
message << " `set personal settings ai.open_ai.image_size 512x512`"
|
55
|
+
return ai_open_ai, message.join("\n")
|
56
|
+
end
|
57
|
+
return ai_open_ai, ''
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.models(open_ai_client, model='')
|
5
|
+
require "openai"
|
6
|
+
user = Thread.current[:user]
|
7
|
+
if model.empty?
|
8
|
+
response = open_ai_client.models.list
|
9
|
+
result = response.body.json().data.id.sort.join("\n")
|
10
|
+
else
|
11
|
+
response = open_ai_client.models.retrieve(id: model)
|
12
|
+
result = response.body
|
13
|
+
end
|
14
|
+
if !response.body.json(:message).empty? and response.body.json(:content).empty?
|
15
|
+
result = response.body.json(:message)
|
16
|
+
end
|
17
|
+
return result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.send_gpt_chat(open_ai_client, model, message)
|
5
|
+
require "openai"
|
6
|
+
user = Thread.current[:user]
|
7
|
+
response = open_ai_client.chat(
|
8
|
+
parameters: {
|
9
|
+
model: model, # Required.
|
10
|
+
messages: [{ role: "user", content: message }], # Required.
|
11
|
+
temperature: 0.7,
|
12
|
+
},
|
13
|
+
)
|
14
|
+
if !response.body.json(:message).empty? and response.body.json(:content).empty?
|
15
|
+
result = response.body.json(:message)
|
16
|
+
return false, result
|
17
|
+
else
|
18
|
+
result = response.body.json(:content)
|
19
|
+
return true, result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.send_image_edit(open_api_client, image, message, size: "")
|
5
|
+
#todo: add size personal settings
|
6
|
+
require "openai"
|
7
|
+
user = Thread.current[:user]
|
8
|
+
|
9
|
+
if size == ""
|
10
|
+
response = open_ai_client.images.edit(parameters: { image: image, prompt: message })
|
11
|
+
else
|
12
|
+
response = open_api_client.images.edit(parameters: { image: image, prompt: message, size: size })
|
13
|
+
end
|
14
|
+
if !response.body.json(:message).empty?
|
15
|
+
return false, "*OpenAI*: #{response.body.json(:message)}"
|
16
|
+
else
|
17
|
+
urls = [response.body.json(:url)].flatten
|
18
|
+
return true, urls
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.send_image_generation(open_ai_client, message, image_size)
|
5
|
+
require "openai"
|
6
|
+
user = Thread.current[:user]
|
7
|
+
#todo: personal settings size #Jal
|
8
|
+
response = open_ai_client.images.generate(parameters: { prompt: message, size: image_size })
|
9
|
+
if !response.body.json(:message).empty?
|
10
|
+
return false, "*OpenAI*: #{response.body.json(:message)}"
|
11
|
+
else
|
12
|
+
urls = [response.body.json(:url)].flatten
|
13
|
+
return true, urls
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.send_image_variation(open_ai_client, image, variations, size: "")
|
5
|
+
#todo: add size personal settings
|
6
|
+
require "openai"
|
7
|
+
user = Thread.current[:user]
|
8
|
+
if size == ""
|
9
|
+
response = open_ai_client.images.variations(parameters: { image: image, n: variations })
|
10
|
+
else
|
11
|
+
response = open_ai_client.images.variations(parameters: { image: image, n: variations, size: size })
|
12
|
+
end
|
13
|
+
if !response.body.json(:message).empty?
|
14
|
+
return false, "*OpenAI*: #{response.body.json(:message)}"
|
15
|
+
else
|
16
|
+
urls = [response.body.json(:url)].flatten
|
17
|
+
return true, urls
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module AI
|
3
|
+
module OpenAI
|
4
|
+
def self.whisper_transcribe(open_ai_client, model, file)
|
5
|
+
require "openai"
|
6
|
+
user = Thread.current[:user]
|
7
|
+
response = open_ai_client.transcribe(
|
8
|
+
parameters: {
|
9
|
+
model: model, # Required.
|
10
|
+
file: File.open(file, "rb"),
|
11
|
+
},
|
12
|
+
)
|
13
|
+
if !response.body.json(:message).empty?
|
14
|
+
return false, response.body.json(:message)
|
15
|
+
else
|
16
|
+
return true, response.body.json(:text)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require_relative 'ai/open_ai/connect'
|
2
|
+
require_relative 'ai/open_ai/send_gpt_chat'
|
3
|
+
require_relative 'ai/open_ai/send_image_edit'
|
4
|
+
require_relative 'ai/open_ai/send_image_variation'
|
5
|
+
require_relative 'ai/open_ai/send_image_generation'
|
6
|
+
require_relative 'ai/open_ai/models'
|
7
|
+
require_relative 'ai/open_ai/whisper_transcribe'
|
8
|
+
|
@@ -1,17 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
if config.simulate and config.key?(:client)
|
8
|
-
client.web_client.conversations_members[channel_id.to_sym].members
|
1
|
+
class SlackSmartBot
|
2
|
+
#todo: add pagination for case more than 1000 members in the channel
|
3
|
+
def get_channel_members(channel_id)
|
4
|
+
begin
|
5
|
+
if channel_id.nil?
|
6
|
+
return nil
|
9
7
|
else
|
10
|
-
|
8
|
+
if config.simulate and config.key?(:client)
|
9
|
+
client.web_client.conversations_members[channel_id.to_sym].members
|
10
|
+
else
|
11
|
+
client.web_client.conversations_members(channel: channel_id, limit: 1000).members
|
12
|
+
end
|
11
13
|
end
|
14
|
+
rescue Exception => stack
|
15
|
+
@logger.warn stack
|
12
16
|
end
|
13
|
-
rescue Exception => stack
|
14
|
-
@logger.warn stack
|
15
|
-
end
|
16
17
|
|
17
|
-
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,35 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
if
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
if bot_is_in
|
11
|
-
client.web_client.users_conversations(exclude_archived: true, limit: 1000, types: "im, public_channel,private_channel").channels
|
1
|
+
class SlackSmartBot
|
2
|
+
def get_channels(bot_is_in: false, types: 'private_channel,public_channel')
|
3
|
+
begin
|
4
|
+
if config.simulate and config.key?(:client)
|
5
|
+
if bot_is_in
|
6
|
+
client.web_client.conversations_members.reject { |r, v| !v.members.include?(config.nick_id) }.values
|
7
|
+
else
|
8
|
+
client.web_client.conversations_members.values
|
9
|
+
end
|
12
10
|
else
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
if bot_is_in
|
12
|
+
client.web_client.users_conversations(exclude_archived: true, limit: 1000, types: "im, public_channel,private_channel").channels
|
13
|
+
else
|
14
|
+
resp = client.web_client.conversations_list(types: types, limit: "600", exclude_archived: "true")
|
15
|
+
channels = resp.channels
|
16
|
+
begin
|
17
|
+
while resp.response_metadata.next_cursor.to_s != ""
|
18
|
+
resp = client.web_client.conversations_list(
|
19
|
+
cursor: resp.response_metadata.next_cursor.to_s,
|
20
|
+
types: types,
|
21
|
+
limit: "600",
|
22
|
+
exclude_archived: "true",
|
23
|
+
)
|
24
|
+
channels += resp.channels
|
25
|
+
end
|
26
|
+
rescue Exception => stack
|
27
|
+
@logger.warn stack
|
24
28
|
end
|
25
|
-
|
26
|
-
@logger.warn stack
|
29
|
+
return channels
|
27
30
|
end
|
28
|
-
return channels
|
29
31
|
end
|
32
|
+
rescue Exception => stack
|
33
|
+
@logger.warn stack
|
34
|
+
return []
|
30
35
|
end
|
31
|
-
rescue Exception => stack
|
32
|
-
@logger.warn stack
|
33
|
-
return []
|
34
36
|
end
|
35
|
-
end
|
37
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class SlackSmartBot
|
2
|
-
def respond_thread(msg, unfurl_links: true, unfurl_media: true)
|
3
|
-
respond(msg, :on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media)
|
2
|
+
def respond_thread(msg='', unfurl_links: true, unfurl_media: true, blocks: [])
|
3
|
+
respond(msg, :on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blocks)
|
4
4
|
end
|
5
5
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module AI
|
5
|
+
module OpenAI
|
6
|
+
def open_ai_chat(message, delete_history)
|
7
|
+
save_stats(__method__)
|
8
|
+
get_personal_settings()
|
9
|
+
@ai_open_ai, message_connect = SlackSmartBot::AI::OpenAI.connect(@ai_open_ai, config, @personal_settings, reconnect: delete_history)
|
10
|
+
respond message_connect if message_connect
|
11
|
+
user = Thread.current[:user]
|
12
|
+
if !@ai_open_ai[user.name].nil? and !@ai_open_ai[user.name][:client].nil?
|
13
|
+
@ai_gpt ||= {}
|
14
|
+
@ai_gpt[user.name] ||= []
|
15
|
+
|
16
|
+
if message == "" # ?? is called
|
17
|
+
@ai_gpt[user.name] = []
|
18
|
+
respond "*GPT*: Let's start a new conversation. Ask me anything."
|
19
|
+
else
|
20
|
+
react :speech_balloon
|
21
|
+
begin
|
22
|
+
@ai_gpt[user.name] = [] if delete_history
|
23
|
+
@ai_gpt[user.name] << message
|
24
|
+
success, res = SlackSmartBot::AI::OpenAI.send_gpt_chat(@ai_open_ai[user.name][:client], @ai_open_ai[user.name].gpt_model, @ai_gpt[user.name].join("\n"))
|
25
|
+
if success
|
26
|
+
@ai_gpt[user.name] << res
|
27
|
+
end
|
28
|
+
respond "*GPT* Session: _<#{@ai_gpt[user.name].first[0..29]}...>_ (id:#{@ai_gpt[user.name].object_id}) \n#{res.strip}"
|
29
|
+
rescue => exception
|
30
|
+
respond "*GPT*: Sorry, I'm having some problems. OpenAI probably is not available. Please try again later."
|
31
|
+
end
|
32
|
+
unreact :speech_balloon
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module AI
|
5
|
+
module OpenAI
|
6
|
+
def open_ai_edit_image(message, files)
|
7
|
+
save_stats(__method__)
|
8
|
+
get_personal_settings()
|
9
|
+
@ai_open_ai, message_connect = SlackSmartBot::AI::OpenAI.connect(@ai_open_ai, config, @personal_settings)
|
10
|
+
respond message_connect if message_connect
|
11
|
+
user = Thread.current[:user]
|
12
|
+
if !@ai_open_ai[user.name].nil? and !@ai_open_ai[user.name][:client].nil?
|
13
|
+
@ai_open_ai_image ||= {}
|
14
|
+
@ai_open_ai_image[user.name] ||= []
|
15
|
+
react :art
|
16
|
+
begin
|
17
|
+
@ai_open_ai_image[user.name] = [] if !files.nil? and files.size == 1
|
18
|
+
if files.nil? or files.size != 1
|
19
|
+
respond "*OpenAI*: Sorry, I need an image to edit. Please upload an image and try again."
|
20
|
+
else
|
21
|
+
require "nice_http"
|
22
|
+
image = "#{config.path}/tmp/#{user.name}_#{@ai_open_ai_image[user.name].object_id}.png"
|
23
|
+
http = NiceHttp.new(host: "https://files.slack.com", headers: { "Authorization" => "Bearer #{config.token}" })
|
24
|
+
res = http.get(files[0].url_private_download, save_data: image)
|
25
|
+
success, res = SlackSmartBot::AI::OpenAI.send_image_edit(@ai_open_ai[user.name].client, image, message, size: @ai_open_ai[user.name][:image_size])
|
26
|
+
|
27
|
+
if success
|
28
|
+
urls = res
|
29
|
+
urls = [urls] if urls.is_a?(String)
|
30
|
+
if urls.nil? or urls.empty?
|
31
|
+
respond "*OpenAI*: Sorry, I'm having some problems. OpenAI was not able to generate an image."
|
32
|
+
else
|
33
|
+
if @ai_open_ai_image[user.name].empty?
|
34
|
+
session_name = "Edit"
|
35
|
+
else
|
36
|
+
session_name = @ai_open_ai_image[user.name].first[0..29]
|
37
|
+
end
|
38
|
+
messagersp = "OpenAI Session: _<#{session_name}...>_ (id:#{@ai_open_ai_image[user.name].object_id})"
|
39
|
+
message = "Edit"
|
40
|
+
require "uri"
|
41
|
+
urls.each do |url|
|
42
|
+
uri = URI.parse(url)
|
43
|
+
require "nice_http"
|
44
|
+
http = NiceHttp.new(host: "https://#{uri.host}")
|
45
|
+
file_path_name = "#{config.path}/tmp/#{user.name}_#{@ai_open_ai_image[user.name].object_id}.png"
|
46
|
+
res = http.get(uri.path + "?#{uri.query}", save_data: file_path_name)
|
47
|
+
send_file(Thread.current[:dest], messagersp, file_path_name, message, "image/png", "png")
|
48
|
+
http.close unless http.nil?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
respond res
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue => exception
|
56
|
+
respond "*OpenAI*: Sorry, I'm having some problems. OpenAI probably is not available. Please try again later."
|
57
|
+
@logger.warn exception
|
58
|
+
end
|
59
|
+
unreact :art
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|