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
@@ -1,55 +1,43 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
countries_candelarific = response.data.json(:countries)
|
15
|
-
if countries_candelarific.is_a?(Array)
|
16
|
-
File.write("#{config.path}/vacations/countries_candelarific.json", countries_candelarific.to_json)
|
17
|
-
@countries_candelarific = JSON.parse(countries_candelarific.to_json)
|
1
|
+
class SlackSmartBot
|
2
|
+
|
3
|
+
def public_holidays(country_name, location, year, month, day, add_stats: true, publish_results: true)
|
4
|
+
save_stats(__method__) if add_stats
|
5
|
+
if config[:public_holidays][:api_key].to_s == ""
|
6
|
+
respond "Sorry, I don't have the API key for the public holidays #{config[:public_holidays][:host]}. Set it up on your SmartBot config file."
|
7
|
+
else
|
8
|
+
begin
|
9
|
+
found_location = true
|
10
|
+
http = NiceHttp.new("#{config[:public_holidays][:host]}/api/v2")
|
11
|
+
if !defined?(@countries_candelarific)
|
12
|
+
if File.exist?("#{config.path}/vacations/countries_candelarific.json")
|
13
|
+
@countries_candelarific = JSON.parse(File.read("#{config.path}/vacations/countries_candelarific.json"))
|
18
14
|
else
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if country.nil?
|
25
|
-
respond "Country #{country_name} not found"
|
26
|
-
else
|
27
|
-
country_original_name = country_name.downcase
|
28
|
-
country_region_id = country_name.downcase
|
29
|
-
country_region_id += "/#{location.downcase}" unless location.empty?
|
30
|
-
country_name = country["country_name"]
|
31
|
-
country_iso = country["iso-3166"]
|
32
|
-
states = []
|
33
|
-
if @public_holidays.key?(country_region_id) and @public_holidays[country_region_id].key?(year.to_s)
|
34
|
-
holidays = @public_holidays[country_region_id][year.to_s]
|
35
|
-
elsif File.exist?(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))
|
36
|
-
holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))).json()
|
37
|
-
elsif !location.empty? and File.exist?(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))
|
38
|
-
holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))).json()
|
39
|
-
holidays.each do |holiday|
|
40
|
-
if holiday.states.is_a?(Array)
|
41
|
-
states << holiday.states.name
|
15
|
+
response = http.get "/countries?api_key=#{config[:public_holidays][:api_key]}"
|
16
|
+
countries_candelarific = response.data.json(:countries)
|
17
|
+
if countries_candelarific.is_a?(Array)
|
18
|
+
File.write("#{config.path}/vacations/countries_candelarific.json", countries_candelarific.to_json)
|
19
|
+
@countries_candelarific = JSON.parse(countries_candelarific.to_json)
|
42
20
|
else
|
43
|
-
|
21
|
+
@countries_candelarific = []
|
44
22
|
end
|
45
23
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
24
|
+
end
|
25
|
+
country = @countries_candelarific.find { |c| c.country_name.match?(/^\s*#{country_name}\s*$/i) }
|
26
|
+
if country.nil?
|
27
|
+
respond "Country #{country_name} not found"
|
49
28
|
else
|
50
|
-
|
51
|
-
|
52
|
-
|
29
|
+
country_original_name = country_name.downcase
|
30
|
+
country_region_id = country_name.downcase
|
31
|
+
country_region_id += "/#{location.downcase}" unless location.empty?
|
32
|
+
country_name = country["country_name"]
|
33
|
+
country_iso = country["iso-3166"]
|
34
|
+
states = []
|
35
|
+
if @public_holidays.key?(country_region_id) and @public_holidays[country_region_id].key?(year.to_s)
|
36
|
+
holidays = @public_holidays[country_region_id][year.to_s]
|
37
|
+
elsif File.exist?(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))
|
38
|
+
holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"))).json()
|
39
|
+
elsif !location.empty? and File.exist?(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))
|
40
|
+
holidays = (File.read(File.join(config.path, "vacations", "#{year}_#{country_original_name.gsub("/", "_").gsub(" ", "_")}.json"))).json()
|
53
41
|
holidays.each do |holiday|
|
54
42
|
if holiday.states.is_a?(Array)
|
55
43
|
states << holiday.states.name
|
@@ -60,85 +48,99 @@ def public_holidays(country_name, location, year, month, day, add_stats: true, p
|
|
60
48
|
holidays = holidays.select { |h| h.states.is_a?(String) and h.states == "All" or (h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0) }
|
61
49
|
holidays_specific = holidays.select { |h| h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0 }
|
62
50
|
found_location = false if holidays_specific.length == 0
|
51
|
+
else
|
52
|
+
response = http.get "/holidays?country=#{country_iso}&year=#{year}&day=#{day}&month=#{month}&api_key=#{config[:public_holidays][:api_key]}"
|
53
|
+
holidays = response.data.json(:holidays)
|
54
|
+
if location != ""
|
55
|
+
holidays.each do |holiday|
|
56
|
+
if holiday.states.is_a?(Array)
|
57
|
+
states << holiday.states.name
|
58
|
+
else
|
59
|
+
states << holiday.states
|
60
|
+
end
|
61
|
+
end
|
62
|
+
holidays = holidays.select { |h| h.states.is_a?(String) and h.states == "All" or (h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0) }
|
63
|
+
holidays_specific = holidays.select { |h| h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0 }
|
64
|
+
found_location = false if holidays_specific.length == 0
|
65
|
+
end
|
66
|
+
if day == "" and month == "" and holidays.is_a?(Array) and holidays.length > 0 and found_location
|
67
|
+
File.write(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"), holidays.to_json) if holidays.is_a?(Array)
|
68
|
+
end
|
63
69
|
end
|
64
|
-
if day == "" and month == ""
|
65
|
-
|
70
|
+
if day == "" and month == ""
|
71
|
+
date = year
|
72
|
+
elsif day == ""
|
73
|
+
date = "#{year}-#{"%02d" % month.to_i}"
|
74
|
+
else
|
75
|
+
date = "#{year}-#{"%02d" % month.to_i}-#{"%02d" % day.to_i}"
|
66
76
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
messages << "\t:spiral_calendar_pad:#{date_holiday}*#{holiday[:name]}* _(#{holiday[:type].join(", ")}) (#{week_day})_"
|
100
|
-
messages << "\t#{holiday[:description]}"
|
101
|
-
if location == ""
|
77
|
+
if holidays.is_a?(Array) and holidays.length > 0 and found_location
|
78
|
+
date_holiday = ""
|
79
|
+
messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
|
80
|
+
num_holidays_to_show = 0
|
81
|
+
all_holidays = []
|
82
|
+
states = []
|
83
|
+
holidays_to_add = []
|
84
|
+
holidays.each do |holiday|
|
85
|
+
if holiday.type.join.match?(/holiday/i)
|
86
|
+
if location == "" or (location != "" and (holiday.states.is_a?(String) and holiday.states == "All") or (holiday.states.is_a?(Array) and holiday.states.name.grep(/#{location}/i).length > 0))
|
87
|
+
holiday_id = "#{holiday[:date][:datetime][:year]}-#{"%02d" % holiday[:date][:datetime][:month]}-#{"%02d" % holiday[:date][:datetime][:day]} #{holiday[:name]}"
|
88
|
+
unless all_holidays.include?(holiday_id) or
|
89
|
+
(day != "" and holiday[:date][:datetime][:day] != day.to_i) or
|
90
|
+
(month != "" and holiday[:date][:datetime][:month] != month.to_i)
|
91
|
+
all_holidays << holiday_id
|
92
|
+
if day == ""
|
93
|
+
m = holiday[:date][:datetime][:month]
|
94
|
+
d = holiday[:date][:datetime][:day]
|
95
|
+
date_holiday = " #{holiday[:date][:datetime][:year]}-#{"%02d" % m}-#{"%02d" % d} "
|
96
|
+
end
|
97
|
+
num_holidays_to_show += 1
|
98
|
+
break if num_holidays_to_show > 30 and publish_results
|
99
|
+
week_day = Date.new(holiday[:date][:datetime][:year], holiday[:date][:datetime][:month], holiday[:date][:datetime][:day]).strftime("%A")
|
100
|
+
messages << "\t:spiral_calendar_pad:#{date_holiday}*#{holiday[:name]}* _(#{holiday[:type].join(", ")}) (#{week_day})_"
|
101
|
+
messages << "\t#{holiday[:description]}"
|
102
|
+
if location == ""
|
103
|
+
if holiday.states.is_a?(Array)
|
104
|
+
messages << "\tLocations: #{holiday.states.name.sort.join(", ")}"
|
105
|
+
else
|
106
|
+
messages << "\tLocations: #{holiday.states}"
|
107
|
+
end
|
108
|
+
end
|
102
109
|
if holiday.states.is_a?(Array)
|
103
|
-
|
110
|
+
states << holiday.states.name
|
104
111
|
else
|
105
|
-
|
112
|
+
states << holiday.states
|
106
113
|
end
|
114
|
+
messages << "\n"
|
115
|
+
holidays_to_add << holiday
|
107
116
|
end
|
108
|
-
if holiday.states.is_a?(Array)
|
109
|
-
states << holiday.states.name
|
110
|
-
else
|
111
|
-
states << holiday.states
|
112
|
-
end
|
113
|
-
messages << "\n"
|
114
|
-
holidays_to_add << holiday
|
115
117
|
end
|
116
118
|
end
|
117
119
|
end
|
118
|
-
|
119
|
-
|
120
|
-
@public_holidays[country_region_id][year.to_s] = holidays_to_add if !@public_holidays[country_region_id].key?(year.to_s)
|
120
|
+
@public_holidays[country_region_id] = {} if !@public_holidays.key?(country_region_id)
|
121
|
+
@public_holidays[country_region_id][year.to_s] = holidays_to_add if !@public_holidays[country_region_id].key?(year.to_s) and date == year
|
121
122
|
|
122
|
-
|
123
|
-
|
124
|
-
|
123
|
+
if num_holidays_to_show > 30
|
124
|
+
messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
|
125
|
+
messages << "Too many holidays to show, please refine your search"
|
126
|
+
end
|
127
|
+
else
|
128
|
+
messages = ["*No holidays found in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}. Be sure the Country and State are written correctly. Try using just the Country, not all countries are supporting States.*"]
|
125
129
|
end
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
messages
|
134
|
-
respond messages[-1] if !publish_results
|
130
|
+
states.flatten!
|
131
|
+
states.uniq!
|
132
|
+
states.delete("All")
|
133
|
+
if states.length > 1 and (location == "" or !found_location)
|
134
|
+
messages << "*All States found in #{date} #{country_name}*: #{states.sort.join(", ")}"
|
135
|
+
respond messages[-1] if !publish_results
|
136
|
+
end
|
137
|
+
respond messages.join("\n") unless !publish_results
|
135
138
|
end
|
136
|
-
|
139
|
+
rescue Exception => stack
|
140
|
+
respond "Sorry, I can't get the public holidays for #{country_name} #{location} in #{date}. Error: #{stack.message}"
|
141
|
+
@logger.fatal stack
|
137
142
|
end
|
138
|
-
|
139
|
-
respond "Sorry, I can't get the public holidays for #{country_name} #{location} in #{date}. Error: #{stack.message}"
|
140
|
-
@logger.fatal stack
|
143
|
+
return (found_location==true and !country.nil?) if !publish_results
|
141
144
|
end
|
142
|
-
return (found_location==true and !country.nil?) if !publish_results
|
143
145
|
end
|
144
|
-
end
|
146
|
+
end
|
@@ -9,13 +9,17 @@ class SlackSmartBot
|
|
9
9
|
else
|
10
10
|
country_region = "#{country}/#{state}"
|
11
11
|
end
|
12
|
-
|
12
|
+
if state == ''
|
13
|
+
respond "Public holidays for *#{country_region}* set. If available States, try with the country and state to be more precise."
|
14
|
+
else
|
15
|
+
respond "Public holidays for *#{country_region}* set."
|
16
|
+
end
|
13
17
|
get_vacations()
|
14
18
|
@vacations[user.name] ||= {}
|
15
19
|
@vacations[user.name][:public_holidays] = country_region
|
16
20
|
update_vacations()
|
17
21
|
else
|
18
|
-
respond "Be sure the country and state are correct."
|
22
|
+
respond "Be sure the country and state are correct. If not displayed available states, try with the country only."
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module Teams
|
5
|
+
def add_team(user, name, options, info)
|
6
|
+
save_stats(__method__)
|
7
|
+
|
8
|
+
get_teams()
|
9
|
+
if @teams.key?(name.to_sym)
|
10
|
+
respond "It seems like the team *#{name}* already exists.\nRelated commands `update team TEAM_NAME PROPERTIES`, `delete team TEAM_NAME`, `see team TEAM_NAME`, `see teams`"
|
11
|
+
else
|
12
|
+
wrong = false
|
13
|
+
team = { members: {}, channels: {} }
|
14
|
+
last_type = nil
|
15
|
+
type_detected = false
|
16
|
+
options.split(/\s+/).each do |opt|
|
17
|
+
type_detected = false
|
18
|
+
if opt.match?(/^\s*$/)
|
19
|
+
#blank
|
20
|
+
elsif opt.match?(/^[\w\-]+$/i)
|
21
|
+
last_type = opt
|
22
|
+
type_detected = true
|
23
|
+
elsif opt.match(/<@(\w+)>/i)
|
24
|
+
team[:members][last_type] ||= []
|
25
|
+
if last_type.nil?
|
26
|
+
wrong = true
|
27
|
+
respond "You need to specify the TYPE for the member."
|
28
|
+
break
|
29
|
+
else
|
30
|
+
member_id = $1
|
31
|
+
member_info = @users.select { |u| u.id == member_id or (u.key?(:enterprise_user) and u.enterprise_user.id == member_id) }[-1]
|
32
|
+
if member_info.nil?
|
33
|
+
@users = get_users()
|
34
|
+
member_info = @users.select { |u| u.id == member_id or (u.key?(:enterprise_user) and u.enterprise_user.id == member_id) }[-1]
|
35
|
+
end
|
36
|
+
team[:members][last_type] << member_info.name
|
37
|
+
end
|
38
|
+
elsif opt.match(/<#(\w+)\|[^>]*>/i)
|
39
|
+
team[:channels][last_type] ||= []
|
40
|
+
if last_type.nil?
|
41
|
+
wrong = true
|
42
|
+
respond "You need to specify the TYPE for the channel."
|
43
|
+
break
|
44
|
+
else
|
45
|
+
channel_id = $1
|
46
|
+
get_channels_name_and_id() unless @channels_name.keys.include?(channel_id)
|
47
|
+
channel = @channels_name[channel_id]
|
48
|
+
channel_members = get_channel_members(channel_id) unless channel.nil?
|
49
|
+
if channel.nil? or !channel_members.include?(config.nick_id)
|
50
|
+
respond ":exclamation: Add the Smart Bot to *<##{channel_id}>* channel first."
|
51
|
+
wrong = true
|
52
|
+
break
|
53
|
+
else
|
54
|
+
team[:channels][last_type] << channel
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
respond "It seems like the members or channel list is not correct. Please double check."
|
59
|
+
wrong = true
|
60
|
+
break
|
61
|
+
end
|
62
|
+
end
|
63
|
+
if type_detected #type added but not added a channel or user
|
64
|
+
respond "It seems like the parameters supplied are not correct. Please double check."
|
65
|
+
wrong = true
|
66
|
+
end
|
67
|
+
|
68
|
+
unless wrong
|
69
|
+
get_teams()
|
70
|
+
team[:info] = info
|
71
|
+
team[:status] = :added
|
72
|
+
team[:user] = user.name
|
73
|
+
team[:creator] = user.name
|
74
|
+
team[:date] = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")[0..18]
|
75
|
+
new_team = {}
|
76
|
+
team[:name] = name
|
77
|
+
new_team[name.to_sym] = team
|
78
|
+
update_teams(new_team)
|
79
|
+
respond "The *#{name}* team has been added."
|
80
|
+
see_teams(user, name, add_stats: false)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module Teams
|
5
|
+
def delete_team(user, team_name)
|
6
|
+
save_stats(__method__) if answer.empty?
|
7
|
+
|
8
|
+
if Thread.current[:dest][0] == "D"
|
9
|
+
respond "This command cannot be called from a DM"
|
10
|
+
else
|
11
|
+
get_teams()
|
12
|
+
if @teams.key?(team_name.to_sym)
|
13
|
+
assigned_members = @teams[team_name.to_sym].members.values.flatten
|
14
|
+
assigned_members.uniq!
|
15
|
+
all_team_members = assigned_members.dup
|
16
|
+
team_members = []
|
17
|
+
if @teams[team_name.to_sym].channels.key?("members")
|
18
|
+
@teams[team_name.to_sym].channels["members"].each do |ch|
|
19
|
+
get_channels_name_and_id() unless @channels_id.key?(ch)
|
20
|
+
tm = get_channel_members(@channels_id[ch])
|
21
|
+
tm.each do |m|
|
22
|
+
user_info = @users.select { |u| u.id == m or (u.key?(:enterprise_user) and u.enterprise_user.id == m) }[-1]
|
23
|
+
team_members << user_info.name unless user_info.is_app_user or user_info.is_bot
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
team_members.flatten!
|
28
|
+
team_members.uniq!
|
29
|
+
all_team_members += team_members
|
30
|
+
all_team_members.uniq!
|
31
|
+
end
|
32
|
+
if !@teams.key?(team_name.to_sym)
|
33
|
+
respond "It seems like the team *#{team_name}* doesn't exist.\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
|
34
|
+
elsif !(all_team_members + [@teams[team_name.to_sym].creator] + config.masters).flatten.include?(user.name)
|
35
|
+
respond "You have to be a member of the team, the creator or a Master admin to be able to delete this team."
|
36
|
+
else
|
37
|
+
if answer.empty?
|
38
|
+
ask "do you really want to delete the #{team_name} team? (yes/no)"
|
39
|
+
else
|
40
|
+
case answer
|
41
|
+
when /yes/i, /yep/i, /sure/i
|
42
|
+
answer_delete
|
43
|
+
@teams.delete(team_name.to_sym)
|
44
|
+
require "fileutils"
|
45
|
+
time_deleted = Time.now.strftime("%Y%m%d%H%M%S")
|
46
|
+
FileUtils.mv(File.join(config.path, "teams", "t_#{team_name}.yaml"),
|
47
|
+
File.join(config.path, "teams", "t_#{team_name}_#{time_deleted}.yaml.deleted"))
|
48
|
+
deleted_memos_file = File.join(config.path, "teams", "t_#{team_name}_memos.yaml.deleted")
|
49
|
+
if File.exist?(deleted_memos_file)
|
50
|
+
FileUtils.mv(deleted_memos_file,
|
51
|
+
File.join(config.path, "teams", "t_#{team_name}_memos_#{time_deleted}.yaml.deleted"))
|
52
|
+
end
|
53
|
+
update_teams()
|
54
|
+
respond "The team #{team_name} has been deleted."
|
55
|
+
when /no/i, /nope/i, /cancel/i
|
56
|
+
answer_delete
|
57
|
+
respond "Ok, the team was not deleted"
|
58
|
+
else
|
59
|
+
respond "I don't understand"
|
60
|
+
ask "do you really want to delete the #{team_name} team? (yes/no)"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module Teams
|
5
|
+
module Memos
|
6
|
+
def add_memo_team(user, privacy, team_name, topic, type, message)
|
7
|
+
save_stats(__method__)
|
8
|
+
|
9
|
+
get_teams()
|
10
|
+
if @teams.key?(team_name.to_sym)
|
11
|
+
assigned_members = @teams[team_name.to_sym].members.values.flatten
|
12
|
+
assigned_members.uniq!
|
13
|
+
all_team_members = assigned_members.dup
|
14
|
+
team_members = []
|
15
|
+
if @teams[team_name.to_sym].channels.key?("members")
|
16
|
+
@teams[team_name.to_sym].channels["members"].each do |ch|
|
17
|
+
get_channels_name_and_id() unless @channels_id.key?(ch)
|
18
|
+
tm = get_channel_members(@channels_id[ch])
|
19
|
+
tm.each do |m|
|
20
|
+
user_info = @users.select { |u| u.id == m or (u.key?(:enterprise_user) and u.enterprise_user.id == m) }[-1]
|
21
|
+
team_members << user_info.name unless user_info.is_app_user or user_info.is_bot
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
team_members.flatten!
|
26
|
+
team_members.uniq!
|
27
|
+
all_team_members += team_members
|
28
|
+
all_team_members.uniq!
|
29
|
+
end
|
30
|
+
search = false
|
31
|
+
if type == "jira"
|
32
|
+
able_to_connect_jira = false
|
33
|
+
begin
|
34
|
+
http = NiceHttp.new(config.jira.host)
|
35
|
+
http.headers.authorization = NiceHttpUtils.basic_authentication(user: config.jira.user, password: config.jira.password)
|
36
|
+
message.gsub!(/^\s*</, "")
|
37
|
+
message.gsub!(/\>$/, "")
|
38
|
+
message.gsub!(/\|.+$/, "")
|
39
|
+
message.gsub!(/^#{config.jira.host}/, "")
|
40
|
+
if message.include?("/browse/")
|
41
|
+
message = message.scan(/\/browse\/(.+)/).join
|
42
|
+
resp = http.get("/rest/api/latest/issue/#{message}")
|
43
|
+
else
|
44
|
+
message.gsub!(/^\/issues\/\?jql=/, "")
|
45
|
+
message.gsub!(" ", "%20")
|
46
|
+
resp = http.get("/rest/api/latest/search/?jql=#{message}")
|
47
|
+
search = true
|
48
|
+
end
|
49
|
+
if resp.code == 200
|
50
|
+
able_to_connect_jira = true
|
51
|
+
else
|
52
|
+
error_code = resp.code
|
53
|
+
if resp.code == 400
|
54
|
+
error_message = resp.data.json(:errorMessages)[-1]
|
55
|
+
else
|
56
|
+
error_message = ""
|
57
|
+
end
|
58
|
+
end
|
59
|
+
http.close
|
60
|
+
rescue => exception
|
61
|
+
@logger.fatal exception
|
62
|
+
end
|
63
|
+
elsif type == "github"
|
64
|
+
able_to_connect_github = false
|
65
|
+
begin
|
66
|
+
search = true if message.include?("?")
|
67
|
+
http = NiceHttp.new(config.github.host)
|
68
|
+
http.headers.authorization = "token #{config.github.token}"
|
69
|
+
message.gsub!(/^\s*</, "")
|
70
|
+
message.gsub!(/\>$/, "")
|
71
|
+
message.gsub!(/\|.+$/, "")
|
72
|
+
message.gsub!(/^#{config.github.host}/, "")
|
73
|
+
message.gsub!("https://github.com", "")
|
74
|
+
message.slice!(0) if message[0] == "/"
|
75
|
+
resp = http.get("/repos/#{message}")
|
76
|
+
if resp.code == 200
|
77
|
+
able_to_connect_github = true
|
78
|
+
else
|
79
|
+
error_code = resp.code
|
80
|
+
if resp.code == 401
|
81
|
+
error_message = resp.data.json(:message)[-1]
|
82
|
+
else
|
83
|
+
error_message = ""
|
84
|
+
end
|
85
|
+
end
|
86
|
+
http.close
|
87
|
+
rescue => exception
|
88
|
+
@logger.fatal exception
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if !@teams.key?(team_name.to_sym)
|
93
|
+
respond "It seems like the team *#{team_name}* doesn't exist\nRelated commands `add team TEAM_NAME PROPERTIES`, `see team TEAM_NAME`, `see teams`"
|
94
|
+
elsif !(all_team_members + config.masters).flatten.include?(user.name)
|
95
|
+
respond "You have to be a member of the team or a Master admin to be able to add a memo to the team."
|
96
|
+
elsif type == "jira" and !able_to_connect_jira
|
97
|
+
if error_message == ""
|
98
|
+
respond "You need to supply the correct credentials for JIRA on the SmartBot settings: `jira: { host: HOST, user: USER, password: PASSWORD }` and a correct JQL string or JQL url"
|
99
|
+
else
|
100
|
+
respond "You need to supply a correct JQL string or JQL url: #{error_message}"
|
101
|
+
end
|
102
|
+
else
|
103
|
+
topic = :no_topic if topic == ""
|
104
|
+
@teams[team_name.to_sym][:memos] ||= []
|
105
|
+
if @teams[team_name.to_sym][:memos].empty? and !@teams[team_name.to_sym].key?(:last_memo_id)
|
106
|
+
memo_id = 1
|
107
|
+
else
|
108
|
+
if @teams[team_name.to_sym].key?(:last_memo_id)
|
109
|
+
memo_id = @teams[team_name.to_sym][:last_memo_id] + 1
|
110
|
+
else
|
111
|
+
memo_id = @teams[team_name.to_sym][:memos].memo_id.flatten.max + 1 #backwards compatibility
|
112
|
+
end
|
113
|
+
end
|
114
|
+
@teams[team_name.to_sym][:last_memo_id] = memo_id
|
115
|
+
@teams[team_name.to_sym][:memos] << {
|
116
|
+
memo_id: memo_id,
|
117
|
+
topic: topic,
|
118
|
+
type: type,
|
119
|
+
privacy: privacy,
|
120
|
+
user: user.name,
|
121
|
+
date: Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")[0..18],
|
122
|
+
message: message,
|
123
|
+
status: ":new: ",
|
124
|
+
search: search,
|
125
|
+
issues: [],
|
126
|
+
comments: [],
|
127
|
+
}
|
128
|
+
update_teams()
|
129
|
+
respond "The memo has been added to *#{team_name}* team. (#{memo_id})"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class SlackSmartBot
|
2
|
+
module Commands
|
3
|
+
module General
|
4
|
+
module Teams
|
5
|
+
module Memos
|
6
|
+
def add_memo_team_comment(user, team_name, memo_id, message)
|
7
|
+
save_stats(__method__)
|
8
|
+
|
9
|
+
get_teams()
|
10
|
+
team_name = team_name.to_sym
|
11
|
+
if @teams.key?(team_name)
|
12
|
+
if @teams[team_name].key?(:memos)
|
13
|
+
memo = @teams[team_name].memos.select { |m| m.memo_id == memo_id.to_i }[-1]
|
14
|
+
if memo
|
15
|
+
memo.comments ||= []
|
16
|
+
memo.comments << { user_name: user.name, user_id: user.id, message: message, time: Time.now.to_s }
|
17
|
+
update_teams()
|
18
|
+
if config.simulate
|
19
|
+
respond "Comment added to memo #{memo_id} in team #{team_name}"
|
20
|
+
else
|
21
|
+
react :spiral_note_pad
|
22
|
+
end
|
23
|
+
else
|
24
|
+
respond "Memo *#{memo_id}* does not exist in team *#{team_name}*."
|
25
|
+
end
|
26
|
+
else
|
27
|
+
respond "There are no memos in team *#{team_name}*."
|
28
|
+
end
|
29
|
+
else
|
30
|
+
respond "Team *#{team_name}* does not exist. Call `see teams` to see the list of teams."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|