slack-smart-bot 1.9.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +184 -16
  3. data/lib/slack/smart-bot/comm/ask.rb +55 -49
  4. data/lib/slack/smart-bot/comm/delete.rb +13 -0
  5. data/lib/slack/smart-bot/comm/dont_understand.rb +3 -3
  6. data/lib/slack/smart-bot/comm/event_hello.rb +8 -4
  7. data/lib/slack/smart-bot/comm/get_channel_members.rb +13 -4
  8. data/lib/slack/smart-bot/comm/get_channels.rb +31 -16
  9. data/lib/slack/smart-bot/comm/get_presence.rb +20 -0
  10. data/lib/slack/smart-bot/comm/get_user_info.rb +12 -8
  11. data/lib/slack/smart-bot/comm/get_users.rb +24 -0
  12. data/lib/slack/smart-bot/comm/react.rb +19 -2
  13. data/lib/slack/smart-bot/comm/respond.rb +224 -53
  14. data/lib/slack/smart-bot/comm/respond_direct.rb +2 -3
  15. data/lib/slack/smart-bot/comm/respond_thread.rb +5 -0
  16. data/lib/slack/smart-bot/comm/send_file.rb +38 -34
  17. data/lib/slack/smart-bot/comm/send_msg_channel.rb +27 -22
  18. data/lib/slack/smart-bot/comm/send_msg_user.rb +59 -33
  19. data/lib/slack/smart-bot/comm/unreact.rb +22 -18
  20. data/lib/slack/smart-bot/comm.rb +4 -0
  21. data/lib/slack/smart-bot/commands/general/add_admin.rb +51 -0
  22. data/lib/slack/smart-bot/commands/general/add_announcement.rb +32 -0
  23. data/lib/slack/smart-bot/commands/general/add_team.rb +80 -0
  24. data/lib/slack/smart-bot/commands/general/allow_access.rb +67 -0
  25. data/lib/slack/smart-bot/commands/general/bot_help.rb +69 -33
  26. data/lib/slack/smart-bot/commands/general/bye_bot.rb +0 -7
  27. data/lib/slack/smart-bot/commands/general/delete_announcement.rb +34 -0
  28. data/lib/slack/smart-bot/commands/general/delete_share.rb +34 -0
  29. data/lib/slack/smart-bot/commands/general/delete_team.rb +34 -0
  30. data/lib/slack/smart-bot/commands/general/deny_access.rb +36 -0
  31. data/lib/slack/smart-bot/commands/general/hi_bot.rb +16 -11
  32. data/lib/slack/smart-bot/commands/general/ping_team.rb +100 -0
  33. data/lib/slack/smart-bot/commands/general/poster.rb +116 -0
  34. data/lib/slack/smart-bot/commands/general/remove_admin.rb +58 -0
  35. data/lib/slack/smart-bot/commands/general/see_access.rb +24 -0
  36. data/lib/slack/smart-bot/commands/general/see_admins.rb +33 -0
  37. data/lib/slack/smart-bot/commands/general/see_announcements.rb +115 -0
  38. data/lib/slack/smart-bot/commands/general/see_command_ids.rb +29 -0
  39. data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +53 -0
  40. data/lib/slack/smart-bot/commands/general/see_shares.rb +41 -0
  41. data/lib/slack/smart-bot/commands/general/see_statuses.rb +91 -0
  42. data/lib/slack/smart-bot/commands/general/see_teams.rb +252 -0
  43. data/lib/slack/smart-bot/commands/general/share_messages.rb +58 -0
  44. data/lib/slack/smart-bot/commands/general/update_team.rb +109 -0
  45. data/lib/slack/smart-bot/commands/general_bot_commands.rb +504 -0
  46. data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +4 -6
  47. data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +45 -14
  48. data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +4 -1
  49. data/lib/slack/smart-bot/commands/on_bot/admin/pause_bot.rb +6 -3
  50. data/lib/slack/smart-bot/commands/on_bot/admin/pause_routine.rb +3 -1
  51. data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +4 -4
  52. data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +8 -2
  53. data/lib/slack/smart-bot/commands/on_bot/admin/see_result_routine.rb +33 -0
  54. data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +13 -10
  55. data/lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb +6 -3
  56. data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +3 -1
  57. data/lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb +4 -1
  58. data/lib/slack/smart-bot/commands/on_bot/admin_master/delete_message.rb +25 -0
  59. data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +1 -0
  60. data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +34 -0
  61. data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +37 -0
  62. data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +4 -5
  63. data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +7 -8
  64. data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +400 -0
  65. data/lib/slack/smart-bot/commands/{general → on_bot/general}/bot_status.rb +3 -4
  66. data/lib/slack/smart-bot/commands/on_bot/general/leaderboard.rb +201 -0
  67. data/lib/slack/smart-bot/commands/{general → on_bot/general}/stop_using_rules.rb +12 -6
  68. data/lib/slack/smart-bot/commands/on_bot/general/suggest_command.rb +36 -0
  69. data/lib/slack/smart-bot/commands/{general → on_bot/general}/use_rules.rb +13 -11
  70. data/lib/slack/smart-bot/commands/{general → on_bot/general}/whats_new.rb +2 -1
  71. data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +4 -5
  72. data/lib/slack/smart-bot/commands/on_bot/repl.rb +76 -21
  73. data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +3 -4
  74. data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +15 -7
  75. data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +5 -6
  76. data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +5 -6
  77. data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +45 -12
  78. data/lib/slack/smart-bot/commands/on_master/admin/kill_bot_on_channel.rb +7 -3
  79. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +4 -1
  80. data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +3 -1
  81. data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +33 -0
  82. data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +39 -0
  83. data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +10 -1
  84. data/lib/slack/smart-bot/commands/on_master/create_bot.rb +28 -14
  85. data/lib/slack/smart-bot/commands/on_master/where_smartbot.rb +41 -0
  86. data/lib/slack/smart-bot/commands.rb +36 -5
  87. data/lib/slack/smart-bot/listen.rb +31 -33
  88. data/lib/slack/smart-bot/process.rb +234 -73
  89. data/lib/slack/smart-bot/process_first.rb +119 -38
  90. data/lib/slack/smart-bot/treat_message.rb +310 -237
  91. data/lib/slack/smart-bot/utils/build_help.rb +2 -2
  92. data/lib/slack/smart-bot/utils/create_routine_thread.rb +81 -46
  93. data/lib/slack/smart-bot/utils/get_access_channels.rb +13 -0
  94. data/lib/slack/smart-bot/utils/get_admins_channels.rb +13 -0
  95. data/lib/slack/smart-bot/utils/get_bots_created.rb +28 -8
  96. data/lib/slack/smart-bot/utils/get_channels_name_and_id.rb +7 -2
  97. data/lib/slack/smart-bot/utils/get_command_ids.rb +84 -0
  98. data/lib/slack/smart-bot/utils/get_help.rb +79 -73
  99. data/lib/slack/smart-bot/utils/get_repls.rb +22 -2
  100. data/lib/slack/smart-bot/utils/get_routines.rb +22 -2
  101. data/lib/slack/smart-bot/utils/get_shares.rb +12 -0
  102. data/lib/slack/smart-bot/utils/get_teams.rb +22 -0
  103. data/lib/slack/smart-bot/utils/has_access.rb +28 -0
  104. data/lib/slack/smart-bot/utils/is_admin.rb +27 -0
  105. data/lib/slack/smart-bot/utils/save_stats.rb +46 -41
  106. data/lib/slack/smart-bot/utils/save_status.rb +67 -0
  107. data/lib/slack/smart-bot/utils/update_access_channels.rb +8 -0
  108. data/lib/slack/smart-bot/utils/update_admins_channels.rb +8 -0
  109. data/lib/slack/smart-bot/utils/update_bots_file.rb +28 -7
  110. data/lib/slack/smart-bot/utils/update_repls.rb +7 -4
  111. data/lib/slack/smart-bot/utils/update_routines.rb +9 -3
  112. data/lib/slack/smart-bot/utils/update_shortcuts_file.rb +13 -6
  113. data/lib/slack/smart-bot/utils/update_teams.rb +16 -0
  114. data/lib/slack/smart-bot/utils.rb +11 -0
  115. data/lib/slack-smart-bot.rb +72 -12
  116. data/lib/slack-smart-bot_general_commands.rb +61 -0
  117. data/lib/slack-smart-bot_general_rules.rb +5 -2
  118. data/lib/slack-smart-bot_rules.rb +43 -17
  119. data/whats_new.txt +20 -15
  120. metadata +76 -9
  121. data/lib/slack/smart-bot/commands/general/bot_stats.rb +0 -313
@@ -1,284 +1,357 @@
1
1
  class SlackSmartBot
2
2
  def treat_message(data, remove_blocks = true)
3
-
3
+ @buffered = false if config[:testing]
4
4
  begin
5
- unless data.text.to_s.match(/\A\s*\z/)
6
- #to remove italic, bold... from data.text since there is no method on slack api
7
- if remove_blocks and !data.blocks.nil? and data.blocks.size > 0
8
- data_text = ''
9
- data.blocks.each do |b|
10
- if b.type == 'rich_text'
11
- if b.elements.size > 0
12
- b.elements.each do |e|
13
- if e.type == 'rich_text_section' or e.type == 'rich_text_preformatted'
14
- if e.elements.size > 0 and (e.elements.type.uniq - ['link', 'text', 'user', 'channel']) == []
15
- data_text += '```' if e.type == 'rich_text_preformatted'
16
- e.elements.each do |el|
17
- if el.type == 'text'
18
- data_text += el.text
19
- elsif el.type == 'user'
20
- data_text += "<@#{el.user_id}>"
21
- elsif el.type == 'channel'
22
- tch = data.text.scan(/(<##{el.channel_id}\|[^\>]+>)/).join
23
- data_text += tch
24
- else
25
- data_text += el.url
5
+ begin
6
+ command_orig = data.text
7
+ unless data.text.to_s.match(/\A\s*\z/)
8
+ #to remove italic, bold... from data.text since there is no method on slack api
9
+ if remove_blocks and !data.blocks.nil? and data.blocks.size > 0
10
+ data_text = ''
11
+ data.blocks.each do |b|
12
+ if b.type == 'rich_text'
13
+ if b.elements.size > 0
14
+ b.elements.each do |e|
15
+ if e.type == 'rich_text_section' or e.type == 'rich_text_preformatted'
16
+ if e.elements.size > 0 and (e.elements.type.uniq - ['link', 'text', 'user', 'channel']) == []
17
+ data_text += '```' if e.type == 'rich_text_preformatted'
18
+ e.elements.each do |el|
19
+ if el.type == 'text'
20
+ data_text += el.text
21
+ elsif el.type == 'user'
22
+ data_text += "<@#{el.user_id}>"
23
+ elsif el.type == 'channel'
24
+ tch = data.text.scan(/(<##{el.channel_id}\|[^\>]*>)/).join
25
+ data_text += tch
26
+ else
27
+ data_text += el.url
28
+ end
26
29
  end
30
+ data_text += '```' if e.type == 'rich_text_preformatted'
27
31
  end
28
- data_text += '```' if e.type == 'rich_text_preformatted'
29
32
  end
30
33
  end
31
34
  end
32
35
  end
33
36
  end
37
+ data.text = data_text unless data_text == ''
34
38
  end
35
- data.text = data_text unless data_text == ''
39
+ data.text = CGI.unescapeHTML(data.text)
40
+ data.text.gsub!("\u00A0", " ") #to change &nbsp; (asc char 160) into blank space
36
41
  end
37
- data.text = CGI.unescapeHTML(data.text)
38
- data.text.gsub!("\u00A0", " ") #to change &nbsp; (asc char 160) into blank space
42
+ data.text.gsub!('‘', "'")
43
+ data.text.gsub!('’', "'")
44
+ data.text.gsub!('“', '"')
45
+ data.text.gsub!('”', '"')
46
+ rescue Exception => exc
47
+ @logger.warn "Impossible to unescape or clean format for data.text:#{data.text}"
48
+ @logger.warn exc.inspect
39
49
  end
40
- data.text.gsub!('‘', "'")
41
- data.text.gsub!('’', "'")
42
- data.text.gsub!('“', '"')
43
- data.text.gsub!('”', '"')
44
- rescue Exception => exc
45
- @logger.warn "Impossible to unescape or clean format for data.text:#{data.text}"
46
- @logger.warn exc.inspect
47
- end
48
- data.routine = false unless data.key?(:routine)
49
-
50
- if config[:testing] and config.on_master_bot
51
- open("#{config.path}/buffer.log", "a") { |f|
52
- f.puts "|#{data.channel}|#{data.user}|#{data.user_name}|#{data.text}"
53
- }
54
- end
55
- if data.key?(:dest) and data.dest.to_s!='' # for run routines and publish on different channels
56
- dest = data.dest
57
- elsif data.channel[0] == "D" or data.channel[0] == "C" or data.channel[0] == "G" #Direct message or Channel or Private Channel
58
- dest = data.channel
59
- else # not treated
60
- dest = nil
61
- end
62
- #todo: sometimes data.user is nil, check the problem.
63
- @logger.warn "!dest is nil. user: #{data.user}, channel: #{data.channel}, message: #{data.text}" if dest.nil?
64
- if !data.files.nil? and data.files.size == 1 and data.text.to_s == "" and data.files[0].filetype == "ruby"
65
- data.text = "ruby"
66
- end
67
- if !dest.nil? and config.on_master_bot and !data.text.nil? and data.text.match(/^ping from (.+)\s*$/) and data.user == config[:nick_id]
68
- @pings << $1
69
- end
70
- typem = :dont_treat
71
- if !dest.nil? and !data.text.nil? and !data.text.to_s.match?(/\A\s*\z/)
72
- #if data.text.match(/^\s*<@#{config[:nick_id]}>\s+(on\s+)?<#(\w+)\|([^>]+)>\s*:?\s*(.*)/im)
73
- if data.text.match(/^\s*<@#{config[:nick_id]}>\s+(on\s+)?((<#\w+\|[^>]+>\s*)+)\s*:?\s*(.*)/im)
74
- channels_rules = $2 #multiple channels @smart-bot on #channel1 #channel2 echo AAA
75
- data_text = $4
76
- channel_rules_name = ''
77
- channel_rules = ''
78
- # to be treated only on the bots of the requested channels
79
- channels_rules.scan(/<#(\w+)\|([^>]+)>/).each do |tcid, tcname|
80
- if @channel_id == tcid
81
- data.text = data_text
82
- typem = :on_call
83
- channel_rules = tcid
84
- channel_rules_name = tcname
85
- break
86
- end
87
- end
88
- elsif data.channel == @master_bot_id
89
- if config.on_master_bot #only to be treated on master bot channel
90
- typem = :on_master
50
+
51
+ unless data.key?(:routine)
52
+ data.routine = false
53
+ data.routine_name = ''
54
+ data.routine_type = ''
55
+ end
56
+ if config[:testing] and config.on_master_bot and !@buffered
57
+ @buffered = true
58
+ open("#{config.path}/buffer.log", "a") { |f|
59
+ f.puts "|#{data.channel}|#{data.user}|#{data.user_name}|#{data.text}"
60
+ }
61
+ end
62
+ if data.key?(:dest) and data.dest.to_s!='' # for run routines and publish on different channels
63
+ dest = data.dest
64
+ elsif data.channel[0] == "D" or data.channel[0] == "C" or data.channel[0] == "G" #Direct message or Channel or Private Channel
65
+ dest = data.channel
66
+ else # not treated
67
+ dest = nil
68
+ end
69
+ #todo: sometimes data.user is nil, check the problem.
70
+ @logger.warn "!dest is nil. user: #{data.user}, channel: #{data.channel}, message: #{data.text}" if dest.nil?
71
+ if !data.files.nil? and data.files.size == 1 and data.text.to_s == "" and data.files[0].filetype == "ruby"
72
+ data.text = "ruby"
73
+ end
74
+ if !dest.nil? and config.on_master_bot and !data.text.nil? and data.text.match(/^ping from (.+)\s*$/) and data.user == config[:nick_id]
75
+ @pings << $1
76
+ end
77
+ typem = :dont_treat
78
+ if data.nil? or data.user.nil? or data.user.to_s==''
79
+ user_info = nil
80
+ @users = get_users() if @users.empty?
81
+ else
82
+ #todo: when changed @questions user_id then move user_info inside the ifs to avoid calling it when not necessary
83
+ user_info = @users.select{|u| u.id == data.user or (u.key?(:enterprise_user) and u.enterprise_user.id == data.user)}[-1]
84
+ if user_info.nil? or user_info.empty?
85
+ @users = get_users()
86
+ user_info = @users.select{|u| u.id == data.user or (u.key?(:enterprise_user) and u.enterprise_user.id == data.user)}[-1]
91
87
  end
92
- elsif @bots_created.key?(data.channel)
93
- if @channel_id == data.channel #only to be treated by the bot on the channel
94
- typem = :on_bot
88
+ end
89
+ if !dest.nil? and !data.text.nil? and !data.text.to_s.match?(/\A\s*\z/)
90
+ get_bots_created()
91
+ if data.channel[0] == "D" and !data.text.to_s.match?(/^\s*<@#{config[:nick_id]}>\s+/) and
92
+ (data.text.to_s.match?(/^\s*(on)?\s*<#\w+\|[^>]*>/i) or data.text.to_s.match?(/^\s*(on)?\s*#\w+/i))
93
+ data.text = "<@#{config[:nick_id]}> " + data.text.to_s
95
94
  end
96
- elsif data.channel[0] == "D" #Direct message
97
- get_rules_imported()
98
- if @rules_imported.key?(data.user) && @rules_imported[data.user].key?(data.user) and
99
- @bots_created.key?(@rules_imported[data.user][data.user])
100
- if @channel_id == @rules_imported[data.user][data.user]
101
- #only to be treated by the channel we are 'using'
95
+ #todo: we need to add mixed channels: @smart-bot on private1 #bot1cm <#CXDDFRDDF|bot2cu>: echo A
96
+ if data.text.match(/\A\^\^+/) # to open a thread it will be only when starting by single ^
97
+ typem = :dont_treat
98
+ elsif data.text.match(/^\s*<@#{config[:nick_id]}>\s+(on\s+)?((<#\w+\|[^>]*>\s*)+)\s*:?\s*(.*)/im) or
99
+ data.text.match(/^\s*<@#{config[:nick_id]}>\s+(on\s+)?((#[a-zA-Z0-9\-\_]+\s*)+)\s*:?\s*(.*)/im) or
100
+ data.text.match(/^\s*<@#{config[:nick_id]}>\s+(on\s+)?(([a-zA-Z0-9\-\_]+\s*)+)\s*:\s*(.*)/im)
101
+ channels_rules = $2 #multiple channels @smart-bot on #channel1 #channel2 echo AAA
102
+ data_text = $4
103
+ channel_rules_name = ''
104
+ channel_rules = ''
105
+ channels_arr = channels_rules.scan(/<#(\w+)\|([^>]*)>/)
106
+ if channels_arr.size == 0
107
+ channels_arr = []
108
+ channels_rules.scan(/([^\s]+)/).each do |cn|
109
+ cna = cn.join.gsub('#','')
110
+ if @channels_name.key?(cna)
111
+ channels_arr << [cna, @channels_name[cna]]
112
+ else
113
+ channels_arr << [@channels_id[cna], cna]
114
+ end
115
+ end
116
+ else
117
+ channels_arr.each do |row|
118
+ row[0] = @channels_id[row[1]] if row[0] == ''
119
+ row[1] = @channels_name[row[0]] if row[1] == ''
120
+ end
121
+ end
122
+
123
+ # to be treated only on the bots of the requested channels
124
+ channels_arr.each do |tcid, tcname|
125
+ if @channel_id == tcid
126
+ data.text = data_text
127
+ typem = :on_call
128
+ channel_rules = tcid
129
+ channel_rules_name = tcname
130
+ break
131
+ elsif @bots_created.key?(@channel_id) and @bots_created[@channel_id][:extended].include?(tcname)
132
+ data.text = data_text
133
+ typem = :on_call
134
+ channel_rules = @channel_id
135
+ channel_rules_name = @channels_name[@channel_id]
136
+ break
137
+ end
138
+ end
139
+
140
+ elsif data.channel == @master_bot_id
141
+ if config.on_master_bot #only to be treated on master bot channel
142
+ typem = :on_master
143
+ end
144
+ elsif @bots_created.key?(data.channel)
145
+ if @channel_id == data.channel #only to be treated by the bot on the channel
146
+ typem = :on_bot
147
+ end
148
+ elsif data.channel[0] == "D" #Direct message
149
+ get_rules_imported()
150
+ if @rules_imported.key?(user_info.name) && @rules_imported[user_info.name].key?(user_info.name) and
151
+ @bots_created.key?(@rules_imported[user_info.name][user_info.name])
152
+ if @channel_id == @rules_imported[user_info.name][user_info.name]
153
+ #only to be treated by the channel we are 'using'
154
+ typem = :on_dm
155
+ end
156
+ elsif config.on_master_bot
157
+ #only to be treated by master bot
102
158
  typem = :on_dm
103
159
  end
104
- elsif config.on_master_bot
105
- #only to be treated by master bot
106
- typem = :on_dm
107
- end
108
- elsif data.channel[0] == "C" or data.channel[0] == "G"
109
- #only to be treated on the channel of the bot. excluding running ruby
110
- if !config.on_master_bot and @bots_created.key?(@channel_id) and @bots_created[@channel_id][:extended].include?(@channels_name[data.channel]) and
111
- !data.text.match?(/^!?\s*(ruby|code)\s+/) and !data.text.match?(/^!?!?\s*(ruby|code)\s+/) and !data.text.match?(/^\^?\s*(ruby|code)\s+/)
112
- typem = :on_extended
113
- elsif config.on_master_bot and (data.text.match?(/^!?\s*(ruby|code)\s+/) or data.text.match?(/^!?!?\s*(ruby|code)\s+/) or data.text.match?(/^\^?\s*(ruby|code)\s+/) )
114
- #or in case of running ruby, the master bot
160
+ elsif data.channel[0] == "C" or data.channel[0] == "G"
161
+ #only to be treated on the channel of the bot. excluding running ruby
162
+ if !config.on_master_bot and @bots_created.key?(@channel_id) and @bots_created[@channel_id][:extended].include?(@channels_name[data.channel]) and
163
+ !data.text.match?(/^!?\s*(ruby|code)\s+/) and !data.text.match?(/^!?!?\s*(ruby|code)\s+/) and !data.text.match?(/^\^?\s*(ruby|code)\s+/)
164
+ typem = :on_extended
165
+ elsif config.on_master_bot and (data.text.match?(/^!?\s*(ruby|code)\s+/) or data.text.match?(/^!?!?\s*(ruby|code)\s+/) or data.text.match?(/^\^?\s*(ruby|code)\s+/) )
166
+ #or in case of running ruby, the master bot
167
+ @bots_created.each do |k, v|
168
+ if v.key?(:extended) and v[:extended].include?(@channels_name[data.channel])
169
+ typem = :on_extended
170
+ break
171
+ end
172
+ end
173
+ end
174
+ extended = false
115
175
  @bots_created.each do |k, v|
116
176
  if v.key?(:extended) and v[:extended].include?(@channels_name[data.channel])
117
- typem = :on_extended
177
+ extended = true
118
178
  break
119
179
  end
120
180
  end
121
- end
122
- if data.channel[0] == "G" and config.on_master_bot and typem != :on_extended #private group
123
- typem = :on_pg
124
- end
125
- end
126
- end
127
- unless typem == :dont_treat
128
- if (Time.now - @last_activity_check) > 60 * 30 #every 30 minutes
129
- @last_activity_check = Time.now
130
- @listening.each do |k,v|
131
- v.each do |kk, vv|
132
- @listening[k].delete(kk) if (Time.now - vv) > 60 * 30
181
+ if data.channel[0] == "G" and config.on_master_bot and !extended #private group
182
+ typem = :on_pg
183
+ elsif data.channel[0] == 'C' and config.on_master_bot and !extended #public group
184
+ typem = :on_pub
133
185
  end
134
- @listening.delete(k) if @listening[k].empty?
135
186
  end
136
187
  end
137
- begin
138
- #todo: when changed @questions user_id then move user_info inside the ifs to avoid calling it when not necessary
139
- user_info = get_user_info(data.user)
188
+ load "#{config.path}/rules/general_commands.rb" if File.exist?("#{config.path}/rules/general_commands.rb") and @datetime_general_commands != File.mtime("#{config.path}/rules/general_commands.rb")
140
189
 
141
- #user_info.user.id = data.user #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
142
- data.user = user_info.user.id #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
143
- if data.thread_ts.nil?
144
- qdest = dest
145
- else
146
- qdest = data.thread_ts
190
+ unless typem == :dont_treat or user_info.nil?
191
+ if (Time.now - @last_activity_check) > 60 * 30 #every 30 minutes
192
+ @last_activity_check = Time.now
193
+ @listening.each do |k,v|
194
+ v.each do |kk, vv|
195
+ @listening[k].delete(kk) if (Time.now - vv) > 60 * 30
196
+ end
197
+ @listening.delete(k) if @listening[k].empty?
198
+ end
147
199
  end
148
- if !answer(user_info.user.name, qdest).empty?
149
- if data.text.match?(/^\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i)
150
- answer_delete(user_info.user.name, qdest)
151
- command = data.text
200
+ begin
201
+ #user_info.id = data.user #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
202
+ data.user = user_info.id #todo: remove this line when slack issue with Wxxxx Uxxxx fixed
203
+ if data.thread_ts.nil?
204
+ qdest = dest
152
205
  else
153
- command = answer(user_info.user.name, qdest)
154
- @answer[user_info.user.name][qdest] = data.text
155
- @questions[user_info.user.name] = data.text # to be backwards compatible #todo remove it when 2.0
206
+ qdest = data.thread_ts
156
207
  end
157
- elsif @repl_sessions.key?(user_info.user.name) and data.channel==@repl_sessions[user_info.user.name][:dest] and
158
- ((@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts == @repl_sessions[user_info.user.name][:thread_ts]) or
159
- (!@repl_sessions[user_info.user.name][:on_thread] and data.thread_ts.to_s == '' ))
160
-
161
- if data.text.match(/^\s*```(.*)```\s*$/im)
162
- @repl_sessions[user_info.user.name][:command] = $1
163
- else
164
- @repl_sessions[user_info.user.name][:command] = data.text
208
+ if !answer(user_info.name, qdest).empty?
209
+ if data.text.match?(/\A\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i)
210
+ answer_delete(user_info.name, qdest)
211
+ command = data.text
212
+ else
213
+ command = answer(user_info.name, qdest)
214
+ @answer[user_info.name][qdest] = data.text
215
+ @questions[user_info.name] = data.text # to be backwards compatible #todo remove it when 2.0
216
+ end
217
+ elsif @repl_sessions.key?(user_info.name) and data.channel==@repl_sessions[user_info.name][:dest] and
218
+ ((@repl_sessions[user_info.name][:on_thread] and data.thread_ts == @repl_sessions[user_info.name][:thread_ts]) or
219
+ (!@repl_sessions[user_info.name][:on_thread] and data.thread_ts.to_s == '' ))
220
+
221
+ if data.text.match(/^\s*```(.*)```\s*$/im)
222
+ @repl_sessions[user_info.name][:command] = $1
223
+ else
224
+ @repl_sessions[user_info.name][:command] = data.text
225
+ end
226
+ command = 'repl'
227
+ else
228
+ command = data.text
165
229
  end
166
- command = 'repl'
167
- else
168
- command = data.text
169
- end
170
-
171
- #when added special characters on the message
172
- if command.match(/\A\s*```(.*)```\s*\z/im)
173
- command = $1
174
- elsif command.size >= 2 and
175
- ((command[0] == "`" and command[-1] == "`") or (command[0] == "*" and command[-1] == "*") or (command[0] == "_" and command[-1] == "_"))
176
- command = command[1..-2]
177
- end
178
230
 
179
- #ruby file attached
180
- if !data.files.nil? and data.files.size == 1 and
181
- (command.match?(/^(ruby|code)\s*$/) or (command.match?(/^\s*$/) and data.files[0].filetype == "ruby") or
182
- (typem == :on_call and data.files[0].filetype == "ruby"))
183
- res = Faraday.new("https://files.slack.com", headers: { "Authorization" => "Bearer #{config[:token]}" }).get(data.files[0].url_private)
184
- command += " ruby" if command != "ruby"
185
- command = "#{command} #{res.body.to_s.force_encoding("UTF-8")}"
186
- end
231
+ #when added special characters on the message
232
+ if command.match(/\A\s*```(.*)```\s*\z/im)
233
+ command = $1
234
+ elsif command.size >= 2 and
235
+ ((command[0] == "`" and command[-1] == "`") or (command[0] == "*" and command[-1] == "*") or (command[0] == "_" and command[-1] == "_"))
236
+ command = command[1..-2]
237
+ end
187
238
 
188
- if typem == :on_call
189
- command = "!" + command unless command[0] == "!" or command.match?(/^\s*$/) or command[0] == "^"
239
+ #ruby file attached
240
+ if !data.files.nil? and data.files.size == 1 and
241
+ (command.match?(/^(ruby|code)\s*$/) or (command.match?(/^\s*$/) and data.files[0].filetype == "ruby") or
242
+ (typem == :on_call and data.files[0].filetype == "ruby"))
243
+ res = Faraday.new("https://files.slack.com", headers: { "Authorization" => "Bearer #{config[:token]}" }).get(data.files[0].url_private)
244
+ command += " ruby" if command != "ruby"
245
+ command = "#{command} #{res.body.to_s.force_encoding("UTF-8")}"
246
+ end
247
+ if typem == :on_call
248
+ command = "!" + command unless command[0] == "!" or command.match?(/^\s*$/) or command[0] == "^"
190
249
 
191
- #todo: add pagination for case more than 1000 channels on the workspace
192
- channels = get_channels()
193
- channel_found = channels.detect { |c| c.name == channel_rules_name }
194
- members = get_channel_members(@channels_id[channel_rules_name]) unless channel_found.nil?
195
- if channel_found.nil?
196
- @logger.fatal "Not possible to find the channel #{channel_rules_name}"
197
- elsif channel_found.name == config.master_channel
198
- respond "You cannot use the rules from Master Channel on any other channel.", data.channel
199
- elsif @status != :on
200
- respond "The bot in that channel is not :on", data.channel
201
- elsif data.user == channel_found.creator or members.include?(data.user)
202
- process_first(user_info.user, command, dest, channel_rules, typem, data.files, data.ts, data.thread_ts, data.routine)
203
- else
204
- respond "You need to join the channel <##{channel_found.id}> to be able to use the rules.", data.channel
250
+ #todo: add pagination for case more than 1000 channels on the workspace
251
+ channels = get_channels()
252
+ channel_found = channels.detect { |c| c.name == channel_rules_name }
253
+ members = get_channel_members(@channels_id[channel_rules_name]) unless channel_found.nil?
254
+ if channel_found.nil?
255
+ @logger.fatal "Not possible to find the channel #{channel_rules_name}"
256
+ elsif channel_found.name == config.master_channel
257
+ respond "You cannot use the rules from Master Channel on any other channel.", data.channel
258
+ elsif @status != :on
259
+ respond "The bot in that channel is not :on", data.channel
260
+ elsif data.user == channel_found.creator or members.include?(data.user)
261
+ process_first(user_info, command, dest, channel_rules, typem, data.files, data.ts, data.thread_ts, data.routine, data.routine_name, data.routine_type, command_orig)
262
+ else
263
+ respond "You need to join the channel <##{channel_found.id}> to be able to use the rules.", data.channel
264
+ end
265
+ elsif config.on_master_bot and typem == :on_extended and
266
+ command.size > 0 and command[0] != "-"
267
+ # to run ruby only from the master bot for the case more than one extended
268
+ process_first(user_info, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts, data.routine, data.routine_name, data.routine_type, command_orig)
269
+ elsif !config.on_master_bot and @bots_created[@channel_id].key?(:extended) and
270
+ @bots_created[@channel_id][:extended].include?(@channels_name[data.channel]) and
271
+ command.size > 0 and command[0] != "-"
272
+ process_first(user_info, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts, data.routine, data.routine_name, data.routine_type, command_orig)
273
+ elsif (dest[0] == "D" or @channel_id == data.channel or data.user == config[:nick_id]) and
274
+ command.size > 0 and command[0] != "-"
275
+ process_first(user_info, command, dest, data.channel, typem, data.files, data.ts, data.thread_ts, data.routine, data.routine_name, data.routine_type, command_orig)
276
+ # if @botname on #channel_rules: do something
277
+ elsif typem == :on_pub or typem == :on_pg
278
+ process_first(user_info, command, dest, channel_rules, typem, data.files, data.ts, data.thread_ts, data.routine, data.routine_name, data.routine_type, command_orig)
205
279
  end
206
- elsif config.on_master_bot and typem == :on_extended and
207
- command.size > 0 and command[0] != "-"
208
- # to run ruby only from the master bot for the case more than one extended
209
- process_first(user_info.user, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts, data.routine)
210
- elsif !config.on_master_bot and @bots_created[@channel_id].key?(:extended) and
211
- @bots_created[@channel_id][:extended].include?(@channels_name[data.channel]) and
212
- command.size > 0 and command[0] != "-"
213
- process_first(user_info.user, command, dest, @channel_id, typem, data.files, data.ts, data.thread_ts, data.routine)
214
- elsif (dest[0] == "D" or @channel_id == data.channel or data.user == config[:nick_id]) and
215
- command.size > 0 and command[0] != "-"
216
- process_first(user_info.user, command, dest, data.channel, typem, data.files, data.ts, data.thread_ts, data.routine)
217
- # if @botname on #channel_rules: do something
280
+ rescue Exception => stack
281
+ @logger.fatal stack
218
282
  end
219
- rescue Exception => stack
220
- @logger.fatal stack
221
- end
222
- else
223
- if !config.on_master_bot and !dest.nil? and (data.channel == @master_bot_id or dest[0] == "D") and
224
- data.text.match?(/^\s*bot\s+status\s*$/i) and @admin_users_id.include?(data.user)
225
- respond "ping from #{config.channel}", dest
226
- elsif !config.on_master_bot and !dest.nil? and data.user == config[:nick_id] and dest == @master_bot_id
227
- # to treat on other bots the status messages populated on master bot
228
- case data.text
229
- when /From now on I'll be on maintenance status/i
230
- sleep 2
231
- if File.exist?("#{config.path}/config_tmp.status")
232
- file_cts = IO.readlines("#{config.path}/config_tmp.status").join
233
- unless file_cts.to_s() == ""
234
- file_cts = eval(file_cts)
235
- if file_cts.is_a?(Hash) and file_cts.key?(:on_maintenance)
236
- config.on_maintenance = file_cts.on_maintenance
283
+
284
+ else
285
+ @logger.warn "Pay attention there is no user on users with id #{data.user}" if user_info.nil?
286
+ if !config.on_master_bot and !dest.nil? and (data.channel == @master_bot_id or dest[0] == "D") and
287
+ data.text.match?(/^\s*(!|!!|\^)?\s*bot\s+status\s*$/i) and @admin_users_id.include?(data.user)
288
+ respond "ping from #{config.channel}", dest
289
+ elsif !config.on_master_bot and !dest.nil? and data.user == config[:nick_id] and dest == @master_bot_id
290
+ # to treat on other bots the status messages populated on master bot
291
+ case data.text
292
+ when /General message has been set\./i, /General message won't be displayed anymore./i
293
+ sleep 2
294
+ if File.exist?("#{config.path}/config_tmp.status")
295
+ file_cts = IO.readlines("#{config.path}/config_tmp.status").join
296
+ unless file_cts.to_s() == ""
297
+ file_cts = eval(file_cts)
298
+ if file_cts.is_a?(Hash) and file_cts.key?(:general_message)
299
+ config.general_message = file_cts.general_message
300
+ end
237
301
  end
238
302
  end
239
- end
240
- when /From now on I won't be on maintenance/i
241
- sleep 2
242
- if File.exist?("#{config.path}/config_tmp.status")
243
- file_cts = IO.readlines("#{config.path}/config_tmp.status").join
244
- unless file_cts.to_s() == ""
245
- file_cts = eval(file_cts)
246
- if file_cts.is_a?(Hash) and file_cts.key?(:on_maintenance)
247
- config.on_maintenance = file_cts.on_maintenance
303
+ when /From now on I'll be on maintenance status/i
304
+ sleep 2
305
+ if File.exist?("#{config.path}/config_tmp.status")
306
+ file_cts = IO.readlines("#{config.path}/config_tmp.status").join
307
+ unless file_cts.to_s() == ""
308
+ file_cts = eval(file_cts)
309
+ if file_cts.is_a?(Hash) and file_cts.key?(:on_maintenance)
310
+ config.on_maintenance = file_cts.on_maintenance
311
+ config.on_maintenance_message = file_cts.on_maintenance_message
312
+ end
248
313
  end
249
314
  end
250
- end
251
-
252
- when /^Bot has been (closed|killed) by/i
253
- sleep 2
254
- get_bots_created()
255
- when /^Changed status on (.+) to :(.+)/i
256
- sleep 2
257
- get_bots_created()
258
- when /extended the rules from (.+) to be used on (.+)\.$/i
259
- sleep 2
260
- get_bots_created()
261
- when /removed the access to the rules of (.+) from (.+)\.$/i
262
- sleep 2
263
- get_bots_created()
264
- when /global shortcut added/
265
- sleep 2
266
- if File.exist?("#{config.path}/shortcuts/shortcuts_global.rb")
267
- file_sc = IO.readlines("#{config.path}/shortcuts/shortcuts_global.rb").join
268
- unless file_sc.to_s() == ""
269
- @shortcuts_global = eval(file_sc)
315
+ when /From now on I won't be on maintenance/i
316
+ sleep 2
317
+ if File.exist?("#{config.path}/config_tmp.status")
318
+ file_cts = IO.readlines("#{config.path}/config_tmp.status").join
319
+ unless file_cts.to_s() == ""
320
+ file_cts = eval(file_cts)
321
+ if file_cts.is_a?(Hash) and file_cts.key?(:on_maintenance)
322
+ config.on_maintenance = file_cts.on_maintenance
323
+ config.on_maintenance_message = file_cts.on_maintenance_message
324
+ end
325
+ end
270
326
  end
271
- end
272
- when /global shortcut deleted/
273
- sleep 2
274
- if File.exist?("#{config.path}/shortcuts/shortcuts_global.rb")
275
- file_sc = IO.readlines("#{config.path}/shortcuts/shortcuts_global.rb").join
276
- unless file_sc.to_s() == ""
277
- @shortcuts_global = eval(file_sc)
327
+
328
+ when /^Bot has been (closed|killed) by/i
329
+ sleep 2
330
+ get_bots_created()
331
+ when /^Changed status on (.+) to :(.+)/i
332
+ sleep 2
333
+ get_bots_created()
334
+ when /extended the rules from (.+) to be used on (.+)\.$/i
335
+ sleep 2
336
+ get_bots_created()
337
+ when /removed the access to the rules of (.+) from (.+)\.$/i
338
+ sleep 2
339
+ get_bots_created()
340
+ when /global shortcut added/
341
+ sleep 2
342
+ if File.exist?("#{config.path}/shortcuts/shortcuts_global.yaml")
343
+ @shortcuts_global = YAML.load(File.read("#{config.path}/shortcuts/shortcuts_global.yaml"))
344
+ end
345
+ when /global shortcut deleted/
346
+ sleep 2
347
+ if File.exist?("#{config.path}/shortcuts/shortcuts_global.yaml")
348
+ @shortcuts_global = YAML.load(File.read("#{config.path}/shortcuts/shortcuts_global.yaml"))
278
349
  end
279
350
  end
280
351
  end
281
352
  end
353
+ rescue Exception => stack
354
+ @logger.fatal stack
282
355
  end
283
356
  end
284
357
  end
@@ -50,8 +50,8 @@ class SlackSmartBot
50
50
  elsif !explanation_done and line.match?(/^\s+[^`].+\s*/i)
51
51
  resf += "\n#{line}"
52
52
  explanation_done = true
53
- elsif !example_done and line.match?(/^\s*_.+_\s*/i)
54
- resf += "\n Example: #{line}"
53
+ elsif !example_done and line.match?(/^\s*>?\s*_.+_\s*$/i)
54
+ resf += "\n Example: #{line.gsub(/^\s*>/,'')}"
55
55
  example_done = true
56
56
  end
57
57
  end