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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -4
  3. data/lib/slack/smart-bot/ai/open_ai/connect.rb +61 -0
  4. data/lib/slack/smart-bot/ai/open_ai/models.rb +21 -0
  5. data/lib/slack/smart-bot/ai/open_ai/send_gpt_chat.rb +24 -0
  6. data/lib/slack/smart-bot/ai/open_ai/send_image_edit.rb +23 -0
  7. data/lib/slack/smart-bot/ai/open_ai/send_image_generation.rb +18 -0
  8. data/lib/slack/smart-bot/ai/open_ai/send_image_variation.rb +22 -0
  9. data/lib/slack/smart-bot/ai/open_ai/whisper_transcribe.rb +21 -0
  10. data/lib/slack/smart-bot/ai.rb +8 -0
  11. data/lib/slack/smart-bot/comm/get_channel_members.rb +15 -13
  12. data/lib/slack/smart-bot/comm/get_channels.rb +31 -29
  13. data/lib/slack/smart-bot/comm/respond_thread.rb +2 -2
  14. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_chat.rb +40 -0
  15. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_edit_image.rb +66 -0
  16. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_generate_image.rb +65 -0
  17. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_models.rb +37 -0
  18. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_variations_image.rb +84 -0
  19. data/lib/slack/smart-bot/commands/general/ai/open_ai/open_ai_whisper.rb +51 -0
  20. data/lib/slack/smart-bot/commands/general/bot_help.rb +1 -0
  21. data/lib/slack/smart-bot/commands/general/personal_settings.rb +38 -0
  22. data/lib/slack/smart-bot/commands/general/poster.rb +107 -104
  23. data/lib/slack/smart-bot/commands/general/public_holidays.rb +116 -114
  24. data/lib/slack/smart-bot/commands/general/set_public_holidays.rb +6 -2
  25. data/lib/slack/smart-bot/commands/general/teams/add_team.rb +87 -0
  26. data/lib/slack/smart-bot/commands/general/teams/delete_team.rb +69 -0
  27. data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team.rb +136 -0
  28. data/lib/slack/smart-bot/commands/general/teams/memos/add_memo_team_comment.rb +37 -0
  29. data/lib/slack/smart-bot/commands/general/teams/memos/delete_memo_team.rb +83 -0
  30. data/lib/slack/smart-bot/commands/general/teams/memos/see_memo_team.rb +97 -0
  31. data/lib/slack/smart-bot/commands/general/teams/memos/see_memos_team.rb +304 -0
  32. data/lib/slack/smart-bot/commands/general/teams/memos/set_memo_status.rb +66 -0
  33. data/lib/slack/smart-bot/commands/general/teams/ping_team.rb +104 -0
  34. data/lib/slack/smart-bot/commands/general/teams/see_teams.rb +236 -0
  35. data/lib/slack/smart-bot/commands/general/teams/see_vacations_team.rb +183 -0
  36. data/lib/slack/smart-bot/commands/general/teams/update_team.rb +137 -0
  37. data/lib/slack/smart-bot/commands/general_bot_commands.rb +905 -741
  38. data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +379 -353
  39. data/lib/slack/smart-bot/commands/on_bot/repl.rb +87 -189
  40. data/lib/slack/smart-bot/commands/on_bot/repl_client.rb +233 -0
  41. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +17 -4
  42. data/lib/slack/smart-bot/commands.rb +26 -10
  43. data/lib/slack/smart-bot/process.rb +14 -3
  44. data/lib/slack/smart-bot/process_first.rb +36 -2
  45. data/lib/slack/smart-bot/treat_message.rb +28 -0
  46. data/lib/slack/smart-bot/utils/check_vacations.rb +1 -0
  47. data/lib/slack/smart-bot/utils/create_routine_thread.rb +1 -1
  48. data/lib/slack/smart-bot/utils/display_calendar.rb +17 -10
  49. data/lib/slack/smart-bot/utils/encryption/decrypt.rb +23 -0
  50. data/lib/slack/smart-bot/utils/encryption/encrypt.rb +27 -0
  51. data/lib/slack/smart-bot/utils/{encryption_get_key_iv.rb → encryption/encryption_get_key_iv.rb} +12 -8
  52. data/lib/slack/smart-bot/utils/get_help.rb +3 -1
  53. data/lib/slack/smart-bot/utils/get_personal_settings.rb +14 -0
  54. data/lib/slack/smart-bot/utils/get_teams.rb +2 -2
  55. data/lib/slack/smart-bot/utils/get_vacations.rb +2 -2
  56. data/lib/slack/smart-bot/utils/save_stats.rb +3 -1
  57. data/lib/slack/smart-bot/utils/update_personal_settings.rb +18 -0
  58. data/lib/slack/smart-bot/utils/update_teams.rb +1 -1
  59. data/lib/slack/smart-bot/utils/update_vacations.rb +1 -1
  60. data/lib/slack/smart-bot/utils.rb +5 -3
  61. data/lib/slack-smart-bot.rb +12 -0
  62. data/whats_new.txt +13 -14
  63. metadata +63 -15
  64. data/lib/slack/smart-bot/commands/general/add_memo_team.rb +0 -117
  65. data/lib/slack/smart-bot/commands/general/add_team.rb +0 -81
  66. data/lib/slack/smart-bot/commands/general/delete_memo_team.rb +0 -69
  67. data/lib/slack/smart-bot/commands/general/delete_team.rb +0 -55
  68. data/lib/slack/smart-bot/commands/general/ping_team.rb +0 -100
  69. data/lib/slack/smart-bot/commands/general/see_memos_team.rb +0 -202
  70. data/lib/slack/smart-bot/commands/general/see_teams.rb +0 -230
  71. data/lib/slack/smart-bot/commands/general/see_vacations_team.rb +0 -136
  72. data/lib/slack/smart-bot/commands/general/set_memo_status.rb +0 -58
  73. data/lib/slack/smart-bot/commands/general/update_team.rb +0 -131
  74. data/lib/slack/smart-bot/utils/decrypt.rb +0 -15
  75. data/lib/slack/smart-bot/utils/encrypt.rb +0 -15
@@ -1,55 +1,43 @@
1
- def public_holidays(country_name, location, year, month, day, add_stats: true, publish_results: true)
2
- save_stats(__method__) if add_stats
3
- if config[:public_holidays][:api_key].to_s == ""
4
- 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."
5
- else
6
- begin
7
- found_location = true
8
- http = NiceHttp.new("#{config[:public_holidays][:host]}/api/v2")
9
- if !defined?(@countries_candelarific)
10
- if File.exist?("#{config.path}/vacations/countries_candelarific.json")
11
- @countries_candelarific = JSON.parse(File.read("#{config.path}/vacations/countries_candelarific.json"))
12
- else
13
- response = http.get "/countries?api_key=#{config[:public_holidays][:api_key]}"
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
- @countries_candelarific = []
20
- end
21
- end
22
- end
23
- country = @countries_candelarific.find { |c| c.country_name.match?(/^\s*#{country_name}\s*$/i) }
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
- states << holiday.states
21
+ @countries_candelarific = []
44
22
  end
45
23
  end
46
- 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) }
47
- holidays_specific = holidays.select { |h| h.states.is_a?(Array) and h.states.name.grep(/^\s*#{location}\s*$/i).length > 0 }
48
- found_location = false if holidays_specific.length == 0
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
- response = http.get "/holidays?country=#{country_iso}&year=#{year}&day=#{day}&month=#{month}&api_key=#{config[:public_holidays][:api_key]}"
51
- holidays = response.data.json(:holidays)
52
- if location != ""
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 == "" and holidays.is_a?(Array) and holidays.length > 0 and found_location
65
- File.write(File.join(config.path, "vacations", "#{year}_#{country_region_id.gsub("/", "_").gsub(" ", "_")}.json"), holidays.to_json) if holidays.is_a?(Array)
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
- end
68
- if day == "" and month == ""
69
- date = year
70
- elsif day == ""
71
- date = "#{year}-#{"%02d" % month}"
72
- else
73
- date = "#{year}-#{"%02d" % month}-#{"%02d" % day}"
74
- end
75
-
76
- if holidays.is_a?(Array) and holidays.length > 0 and found_location
77
- date_holiday = ""
78
- messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
79
- num_holidays_to_show = 0
80
- all_holidays = []
81
- states = []
82
- holidays_to_add = []
83
- holidays.each do |holiday|
84
- if holiday.type.join.match?(/holiday/i)
85
- 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))
86
- holiday_id = "#{holiday[:date][:datetime][:year]}-#{"%02d" % holiday[:date][:datetime][:month]}-#{"%02d" % holiday[:date][:datetime][:day]} #{holiday[:name]}"
87
- unless all_holidays.include?(holiday_id) or
88
- (day != "" and holiday[:date][:datetime][:day] != day.to_i) or
89
- (month != "" and holiday[:date][:datetime][:month] != month.to_i)
90
- all_holidays << holiday_id
91
- if day == ""
92
- m = holiday[:date][:datetime][:month]
93
- d = holiday[:date][:datetime][:day]
94
- date_holiday = " #{holiday[:date][:datetime][:year]}-#{"%02d" % m}-#{"%02d" % d} "
95
- end
96
- num_holidays_to_show += 1
97
- break if num_holidays_to_show > 30 and publish_results
98
- week_day = Date.new(holiday[:date][:datetime][:year], holiday[:date][:datetime][:month], holiday[:date][:datetime][:day]).strftime("%A")
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
- messages << "\tLocations: #{holiday.states.name.sort.join(", ")}"
110
+ states << holiday.states.name
104
111
  else
105
- messages << "\tLocations: #{holiday.states}"
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
- end
119
- @public_holidays[country_region_id] = {} if !@public_holidays.key?(country_region_id)
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
- if num_holidays_to_show > 30
123
- messages = ["*Holidays in #{country_name}#{" #{location.downcase.capitalize}" unless location.empty?} in #{date}*"]
124
- messages << "Too many holidays to show, please refine your search"
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
- else
127
- 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.*"]
128
- end
129
- states.flatten!
130
- states.uniq!
131
- states.delete("All")
132
- if states.length > 1 and (location == "" or !found_location)
133
- messages << "*All States found in #{date} #{country_name}*: #{states.sort.join(", ")}"
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
- respond messages.join("\n") unless !publish_results
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
- rescue Exception => stack
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
- respond "Public holidays for *#{country_region}* set."
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