slack-smart-bot 1.10.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +134 -23
  3. data/lib/slack/smart-bot/comm/delete.rb +13 -0
  4. data/lib/slack/smart-bot/comm/dont_understand.rb +2 -2
  5. data/lib/slack/smart-bot/comm/get_channel_members.rb +7 -3
  6. data/lib/slack/smart-bot/comm/get_presence.rb +20 -0
  7. data/lib/slack/smart-bot/comm/get_users.rb +1 -1
  8. data/lib/slack/smart-bot/comm/respond.rb +24 -13
  9. data/lib/slack/smart-bot/comm/send_msg_user.rb +12 -11
  10. data/lib/slack/smart-bot/comm/set_status.rb +21 -0
  11. data/lib/slack/smart-bot/comm.rb +3 -0
  12. data/lib/slack/smart-bot/commands/general/add_admin.rb +51 -0
  13. data/lib/slack/smart-bot/commands/general/add_announcement.rb +1 -1
  14. data/lib/slack/smart-bot/commands/general/add_memo_team.rb +117 -0
  15. data/lib/slack/smart-bot/commands/general/add_team.rb +80 -0
  16. data/lib/slack/smart-bot/commands/general/add_vacation.rb +51 -0
  17. data/lib/slack/smart-bot/commands/general/allow_access.rb +67 -0
  18. data/lib/slack/smart-bot/commands/general/bot_help.rb +20 -11
  19. data/lib/slack/smart-bot/commands/general/delete_announcement.rb +1 -1
  20. data/lib/slack/smart-bot/commands/general/delete_memo_team.rb +69 -0
  21. data/lib/slack/smart-bot/commands/general/delete_share.rb +1 -1
  22. data/lib/slack/smart-bot/commands/general/delete_team.rb +54 -0
  23. data/lib/slack/smart-bot/commands/general/deny_access.rb +36 -0
  24. data/lib/slack/smart-bot/commands/general/ping_team.rb +100 -0
  25. data/lib/slack/smart-bot/commands/general/poster.rb +116 -0
  26. data/lib/slack/smart-bot/commands/general/remove_admin.rb +58 -0
  27. data/lib/slack/smart-bot/commands/general/remove_vacation.rb +27 -0
  28. data/lib/slack/smart-bot/commands/general/see_access.rb +24 -0
  29. data/lib/slack/smart-bot/commands/general/see_admins.rb +33 -0
  30. data/lib/slack/smart-bot/commands/general/see_announcements.rb +7 -5
  31. data/lib/slack/smart-bot/commands/general/see_command_ids.rb +29 -0
  32. data/lib/slack/smart-bot/commands/general/see_favorite_commands.rb +3 -4
  33. data/lib/slack/smart-bot/commands/general/see_statuses.rb +34 -21
  34. data/lib/slack/smart-bot/commands/general/see_teams.rb +402 -0
  35. data/lib/slack/smart-bot/commands/general/see_vacations.rb +58 -0
  36. data/lib/slack/smart-bot/commands/general/see_vacations_team.rb +136 -0
  37. data/lib/slack/smart-bot/commands/general/set_memo_status.rb +58 -0
  38. data/lib/slack/smart-bot/commands/general/share_messages.rb +1 -1
  39. data/lib/slack/smart-bot/commands/general/update_team.rb +130 -0
  40. data/lib/slack/smart-bot/commands/general_bot_commands.rb +442 -13
  41. data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +2 -1
  42. data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +2 -1
  43. data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +2 -1
  44. data/lib/slack/smart-bot/commands/on_bot/admin/pause_bot.rb +2 -1
  45. data/lib/slack/smart-bot/commands/on_bot/admin/pause_routine.rb +2 -1
  46. data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +2 -1
  47. data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +3 -2
  48. data/lib/slack/smart-bot/commands/on_bot/admin/see_result_routine.rb +2 -1
  49. data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +10 -9
  50. data/lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb +2 -1
  51. data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +2 -1
  52. data/lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb +2 -1
  53. data/lib/slack/smart-bot/commands/on_bot/admin_master/delete_message.rb +25 -0
  54. data/lib/slack/smart-bot/commands/on_bot/admin_master/get_bot_logs.rb +1 -0
  55. data/lib/slack/smart-bot/commands/on_bot/admin_master/react_to.rb +3 -1
  56. data/lib/slack/smart-bot/commands/on_bot/admin_master/send_message.rb +15 -2
  57. data/lib/slack/smart-bot/commands/on_bot/delete_repl.rb +2 -1
  58. data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +5 -4
  59. data/lib/slack/smart-bot/commands/on_bot/general/bot_stats.rb +416 -0
  60. data/lib/slack/smart-bot/commands/{general → on_bot/general}/bot_status.rb +1 -0
  61. data/lib/slack/smart-bot/commands/{general → on_bot/general}/leaderboard.rb +1 -0
  62. data/lib/slack/smart-bot/commands/{general → on_bot/general}/stop_using_rules.rb +1 -0
  63. data/lib/slack/smart-bot/commands/{general → on_bot/general}/suggest_command.rb +6 -0
  64. data/lib/slack/smart-bot/commands/{general → on_bot/general}/use_rules.rb +1 -0
  65. data/lib/slack/smart-bot/commands/{general → on_bot/general}/whats_new.rb +2 -1
  66. data/lib/slack/smart-bot/commands/on_bot/get_repl.rb +2 -1
  67. data/lib/slack/smart-bot/commands/on_bot/kill_repl.rb +32 -0
  68. data/lib/slack/smart-bot/commands/on_bot/repl.rb +73 -15
  69. data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +1 -0
  70. data/lib/slack/smart-bot/commands/on_bot/run_repl.rb +117 -28
  71. data/lib/slack/smart-bot/commands/on_bot/see_repls.rb +2 -1
  72. data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +3 -2
  73. data/lib/slack/smart-bot/commands/on_master/admin/kill_bot_on_channel.rb +5 -4
  74. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +3 -2
  75. data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +2 -1
  76. data/lib/slack/smart-bot/commands/on_master/admin_master/publish_announcements.rb +6 -3
  77. data/lib/slack/smart-bot/commands/on_master/admin_master/set_general_message.rb +2 -1
  78. data/lib/slack/smart-bot/commands/on_master/admin_master/set_maintenance.rb +2 -1
  79. data/lib/slack/smart-bot/commands/on_master/create_bot.rb +1 -0
  80. data/lib/slack/smart-bot/commands/on_master/where_smartbot.rb +41 -0
  81. data/lib/slack/smart-bot/commands.rb +30 -7
  82. data/lib/slack/smart-bot/listen.rb +30 -30
  83. data/lib/slack/smart-bot/process.rb +53 -23
  84. data/lib/slack/smart-bot/process_first.rb +2 -2
  85. data/lib/slack/smart-bot/treat_message.rb +23 -17
  86. data/lib/slack/smart-bot/utils/build_help.rb +1 -1
  87. data/lib/slack/smart-bot/utils/check_vacations.rb +43 -0
  88. data/lib/slack/smart-bot/utils/create_routine_thread.rb +1 -1
  89. data/lib/slack/smart-bot/utils/get_access_channels.rb +13 -0
  90. data/lib/slack/smart-bot/utils/get_admins_channels.rb +33 -0
  91. data/lib/slack/smart-bot/utils/get_bots_created.rb +27 -10
  92. data/lib/slack/smart-bot/utils/get_channels_name_and_id.rb +7 -2
  93. data/lib/slack/smart-bot/utils/get_command_ids.rb +84 -0
  94. data/lib/slack/smart-bot/utils/get_help.rb +36 -19
  95. data/lib/slack/smart-bot/utils/get_repls.rb +22 -2
  96. data/lib/slack/smart-bot/utils/get_routines.rb +22 -2
  97. data/lib/slack/smart-bot/utils/get_teams.rb +22 -0
  98. data/lib/slack/smart-bot/utils/get_vacations.rb +22 -0
  99. data/lib/slack/smart-bot/utils/has_access.rb +25 -9
  100. data/lib/slack/smart-bot/utils/is_admin.rb +27 -0
  101. data/lib/slack/smart-bot/utils/save_stats.rb +52 -42
  102. data/lib/slack/smart-bot/utils/save_status.rb +22 -7
  103. data/lib/slack/smart-bot/utils/update_access_channels.rb +8 -0
  104. data/lib/slack/smart-bot/utils/update_admins_channels.rb +25 -0
  105. data/lib/slack/smart-bot/utils/update_bots_file.rb +28 -7
  106. data/lib/slack/smart-bot/utils/update_repls.rb +7 -4
  107. data/lib/slack/smart-bot/utils/update_routines.rb +9 -3
  108. data/lib/slack/smart-bot/utils/update_shortcuts_file.rb +13 -6
  109. data/lib/slack/smart-bot/utils/update_teams.rb +16 -0
  110. data/lib/slack/smart-bot/utils/update_vacations.rb +16 -0
  111. data/lib/slack/smart-bot/utils.rb +11 -0
  112. data/lib/slack-smart-bot.rb +50 -12
  113. data/lib/slack-smart-bot_general_commands.rb +16 -1
  114. data/whats_new.txt +12 -30
  115. metadata +78 -21
  116. data/lib/slack/smart-bot/commands/general/bot_stats.rb +0 -314
@@ -0,0 +1,84 @@
1
+ class SlackSmartBot
2
+ def get_command_ids
3
+ commands = {
4
+ general: [],
5
+ on_bot_general: [],
6
+ on_bot_on_demand: [],
7
+ on_bot_admin: [],
8
+ on_bot_master_admin: [],
9
+ on_extended: [],
10
+ on_master: [],
11
+ on_master_admin: [],
12
+ on_master_master_admin: [],
13
+ general_commands: [],
14
+ general_rules: [],
15
+ rules: []
16
+ }
17
+ typem = Thread.current[:typem]
18
+ user = Thread.current[:user]
19
+ # :on_call, :on_bot, :on_extended, :on_dm, :on_master, :on_pg, :on_pub
20
+ admin = is_admin?(user.name)
21
+
22
+ commands[:general] = (Dir.entries("#{__dir__}/../commands/general/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
23
+ general = File.read("#{__dir__}/../commands/general_bot_commands.rb")
24
+ commands[:general] += general.scan(/^\s*#\s*help\w*:\s+command_id:\s+:(\w+)\s*$/i).flatten
25
+ commands[:general].uniq!
26
+
27
+ if typem == :on_bot or typem == :on_master
28
+ commands[:on_bot_general] = (Dir.entries("#{__dir__}/../commands/on_bot/general/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
29
+ end
30
+
31
+ if typem == :on_bot or typem == :on_master
32
+ commands[:on_bot_on_demand] = (Dir.entries("#{__dir__}/../commands/on_bot/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
33
+ end
34
+
35
+ if (typem == :on_bot or typem == :on_master) and admin
36
+ commands[:on_bot_admin] = (Dir.entries("#{__dir__}/../commands/on_bot/admin/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
37
+ end
38
+
39
+ if (typem == :on_bot or typem == :on_master) and config.masters.include?(user.name)
40
+ commands[:on_bot_master_admin] = (Dir.entries("#{__dir__}/../commands/on_bot/admin_master/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
41
+ end
42
+
43
+ if typem == :on_extended
44
+ commands[:on_extended] = (Dir.entries("#{__dir__}/../commands/on_extended/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
45
+ commands[:on_extended]+= ['repl', 'see_repls', 'get_repl', 'run_repl', 'delete_repl', 'kill_repl', 'ruby_code']
46
+ end
47
+
48
+ if typem == :on_master
49
+ commands[:on_master] = (Dir.entries("#{__dir__}/../commands/on_master/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
50
+ end
51
+
52
+ if typem == :on_master and admin
53
+ commands[:on_master_admin] = (Dir.entries("#{__dir__}/../commands/on_master/admin/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
54
+ end
55
+
56
+ if typem == :on_master and config.masters.include?(user.name)
57
+ commands[:on_master_master_admin] = (Dir.entries("#{__dir__}/../commands/on_master/admin_master/").select { |e| e.match?(/\.rb/) }).sort.join('|').gsub('.rb','').split('|')
58
+ end
59
+
60
+ if File.exist?("#{config.path}/rules/general_commands.rb")
61
+ general_commands = File.read("#{config.path}/rules/general_commands.rb")
62
+ commands[:general_commands] = general_commands.scan(/^\s*#\s*help\w*:\s+command_id:\s+:(\w+)\s*$/i).flatten
63
+ commands[:general_commands]+= general_commands.scan(/^\s*save_stats\(?\s*:(\w+)\s*,?/i).flatten
64
+ commands[:general_commands].uniq!
65
+ end
66
+
67
+ if typem == :on_extended or typem ==:on_call or typem == :on_bot or typem == :on_master or (typem == :on_dm and Thread.current[:using_channel].to_s != '')
68
+ if Thread.current.key?(:rules_file) and File.exist?(config.path + Thread.current[:rules_file])
69
+ rules = File.read(config.path + Thread.current[:rules_file])
70
+ commands[:rules] = rules.scan(/^\s*#\s*help\w*:\s+command_id:\s+:(\w+)\s*$/i).flatten
71
+ commands[:rules]+= rules.scan(/^\s*save_stats\(?\s*:(\w+)\s*,?/i).flatten
72
+ commands[:rules].uniq!
73
+
74
+ if File.exist?("#{config.path}/rules/general_rules.rb")
75
+ general_rules = File.read("#{config.path}/rules/general_rules.rb")
76
+ commands[:general_rules] = general_rules.scan(/^\s*#\s*help\w*:\s+command_id:\s+:(\w+)\s*$/i).flatten
77
+ commands[:general_rules]+= general_rules.scan(/^\s*save_stats\(?\s*:(\w+)\s*,?/i).flatten
78
+ commands[:general_rules].uniq!
79
+ end
80
+ end
81
+ end
82
+ return commands
83
+ end
84
+ end
@@ -1,14 +1,18 @@
1
1
  class SlackSmartBot
2
2
  def get_help(rules_file, dest, from, only_rules, expanded, descriptions: true, only_normal_user: false)
3
3
  order = {
4
- general: [:whats_new, :hi_bot, :bye_bot, :bot_help, :suggest_command, :bot_status, :use_rules, :stop_using_rules, :bot_stats, :leaderboard],
5
- on_bot: [:ruby_code, :repl, :get_repl, :run_repl, :delete_repl, :see_repls, :add_shortcut, :delete_shortcut, :see_shortcuts],
4
+ general: [:bot_help, :hi_bot, :bye_bot, :add_admin, :remove_admin, :see_admins, :poster, :add_announcement, :delete_announcement,
5
+ :see_announcements, :see_command_ids, :share_messages, :see_shares, :delete_share, :see_favorite_commands, :see_statuses,
6
+ :allow_access, :see_access, :deny_access, :add_team, :add_memo_team, :delete_memo_team, :set_memo_status, :see_teams, :update_team, :ping_team, :delete_team,
7
+ :add_vacation, :remove_vacation, :see_vacations, :see_vacations_team],
8
+ on_bot_general: [:whats_new, :suggest_command, :bot_status, :use_rules, :stop_using_rules, :bot_stats, :leaderboard],
9
+ on_bot: [:ruby_code, :repl, :get_repl, :run_repl, :delete_repl, :see_repls, :kill_repl, :add_shortcut, :delete_shortcut, :see_shortcuts],
6
10
  on_bot_admin: [:extend_rules, :stop_using_rules_on, :start_bot, :pause_bot, :add_routine,
7
11
  :see_routines, :start_routine, :pause_routine, :remove_routine, :see_result_routine, :run_routine]
8
12
  }
9
13
  if config.masters.include?(from)
10
14
  user_type = :master # master admin
11
- elsif config.admins.include?(from)
15
+ elsif is_admin?(from)
12
16
  user_type = :admin
13
17
  else
14
18
  user_type = :normal #normal user
@@ -66,9 +70,15 @@ class SlackSmartBot
66
70
  end
67
71
 
68
72
  help[:general_commands_file] = build_help("#{__dir__}/../commands/general_bot_commands.rb", expanded)[user_type].values.join("\n") + "\n" unless only_rules
69
- if File.exists?(config.path + '/rules/general_commands.rb') and !only_rules
73
+ if File.exist?(config.path + '/rules/general_commands.rb') and !only_rules
70
74
  help[:general_commands_file] += build_help(config.path+'/rules/general_commands.rb', expanded)[user_type].values.join("\n") + "\n"
71
75
  end
76
+ if help.key?(:on_bot)
77
+ commands_on_extended_from_on_bot = [:repl, :see_repls, :get_repl, :run_repl, :delete_repl, :kill_repl, :ruby_code]
78
+ commands_on_extended_from_on_bot.each do |cm|
79
+ help[:on_extended][cm] = help[:on_bot][cm] if help[:on_bot].key?(cm)
80
+ end
81
+ end
72
82
  help = remove_hash_keys(help, :admin_master) unless user_type == :master
73
83
  help = remove_hash_keys(help, :admin) unless user_type == :admin or user_type == :master
74
84
  help = remove_hash_keys(help, :on_master) unless channel_type == :master_bot
@@ -101,36 +111,33 @@ class SlackSmartBot
101
111
  You need to join the specified channel to be able to use those rules.
102
112
  Also you can use this command to call another bot from a channel with a running bot.
103
113
  \n"
104
- txt +="
105
- The commands you will be able to use from a channel without a bot:
106
- *bot rules*, *ruby CODE*, *add shortcut NAME: COMMAND*, *delete shortcut NAME*, *see shortcuts*, *shortcut NAME*
107
- *And all the specific rules of the Channel*\n"
108
114
  end
109
115
 
110
- if help.key?(:general) and channel_type != :external and channel_type != :extended
116
+ if help.key?(:general_commands_file)
117
+ txt += "===================================
118
+ *General commands on any channel where the Smart Bot is a member:*\n" if descriptions
119
+ txt += help.general_commands_file
120
+ end
121
+
122
+ if help.key?(:on_bot) and help.on_bot.key?(:general) and channel_type != :external and channel_type != :extended
111
123
  if descriptions
112
124
  if channel_type == :direct
113
125
  txt += "===================================
114
126
  *General commands:*\n"
115
127
  else
116
128
  txt += "===================================
117
- *General commands even when the Smart Bot is not listening to you:*\n"
129
+ *General commands on Bot channel even when the Smart Bot is not listening to you:*\n"
118
130
  end
119
131
  end
120
- order.general.each do |o|
121
- txt += help.general[o]
132
+ order.on_bot_general.each do |o|
133
+ txt += help.on_bot.general[o]
122
134
  end
123
135
  if channel_type == :master_bot
124
136
  txt += help.on_master.create_bot
137
+ txt += help.on_master.where_smartbot
125
138
  end
126
139
  end
127
140
 
128
- if help.key?(:general_commands_file)
129
- txt += "===================================
130
- *General commands on any channel where the Smart Bot is a member:*\n" if descriptions
131
- txt += help.general_commands_file
132
- end
133
-
134
141
  if help.key?(:on_bot) and channel_type != :external and channel_type != :extended
135
142
  if descriptions
136
143
  if channel_type == :direct
@@ -138,13 +145,23 @@ class SlackSmartBot
138
145
  *General commands on bot, DM or on external call on demand:*\n"
139
146
  else
140
147
  txt += "===================================
141
- *General commands only when the Smart Bot is listening to you or on demand:*\n"
148
+ *General commands on Bot channel only when the Smart Bot is listening to you or on demand:*\n"
142
149
  end
143
150
  end
144
151
  order.on_bot.each do |o|
145
152
  txt += help.on_bot[o]
146
153
  end
147
154
  end
155
+ if help.key?(:on_extended) and channel_type == :extended and help[:on_extended].keys.size > 0
156
+ if descriptions
157
+ txt += "===================================
158
+ *General commands on Extended channel only on demand:*\n"
159
+ end
160
+ commands_on_extended_from_on_bot.each do |o|
161
+ txt += help.on_extended[o]
162
+ end
163
+ end
164
+
148
165
  if help.key?(:on_bot) and help.on_bot.key?(:admin) and channel_type != :external and channel_type != :extended
149
166
  txt += "===================================
150
167
  *Admin commands:*\n\n" if descriptions
@@ -1,11 +1,31 @@
1
1
  class SlackSmartBot
2
2
 
3
3
  def get_repls(channel = @channel_id)
4
- if File.exist?("#{config.path}/repl/repls_#{channel}.rb")
4
+ require 'yaml'
5
+ repl_file = "#{config.path}/repl/repls_#{channel}.yaml"
6
+
7
+ if File.exist?("#{config.path}/repl/repls_#{channel}.rb") #backwards compatible
5
8
  file_conf = IO.readlines("#{config.path}/repl/repls_#{channel}.rb").join
6
- unless file_conf.to_s() == ""
9
+ if file_conf.to_s() == ""
10
+ @repls = {}
11
+ else
7
12
  @repls = eval(file_conf)
8
13
  end
14
+ File.open(repl_file, 'w') {|file| file.write(@repls.to_yaml) }
15
+ File.delete("#{config.path}/repl/repls_#{channel}.rb")
16
+ end
17
+
18
+ if File.exist?(repl_file)
19
+ repls = @repls
20
+ 10.times do
21
+ repls = YAML.load(File.read(repl_file))
22
+ if repls.is_a?(Hash)
23
+ break
24
+ else
25
+ sleep (0.1*(rand(2)+1))
26
+ end
27
+ end
28
+ @repls = repls unless repls.is_a?(FalseClass)
9
29
  end
10
30
  end
11
31
  end
@@ -1,11 +1,31 @@
1
1
  class SlackSmartBot
2
2
 
3
3
  def get_routines(channel = @channel_id)
4
- if File.exist?("#{config.path}/routines/routines_#{channel}.rb")
4
+ require 'yaml'
5
+ routines_file = "#{config.path}/routines/routines_#{channel}.yaml"
6
+
7
+ if File.exist?("#{config.path}/routines/routines_#{channel}.rb") #backwards compatible
5
8
  file_conf = IO.readlines("#{config.path}/routines/routines_#{channel}.rb").join
6
- unless file_conf.to_s() == ""
9
+ if file_conf.to_s() == ""
10
+ @routines = {}
11
+ else
7
12
  @routines = eval(file_conf)
8
13
  end
14
+ File.open(routines_file, 'w') {|file| file.write(@routines.to_yaml) }
15
+ File.delete("#{config.path}/routines/routines_#{channel}.rb")
16
+ end
17
+
18
+ if File.exist?(routines_file)
19
+ routines = @routines
20
+ 10.times do
21
+ routines = YAML.load(File.read(routines_file))
22
+ if routines.is_a?(Hash)
23
+ break
24
+ else
25
+ sleep (0.1*(rand(2)+1))
26
+ end
27
+ end
28
+ @routines = routines unless routines.is_a?(FalseClass)
9
29
  end
10
30
  end
11
31
  end
@@ -0,0 +1,22 @@
1
+ class SlackSmartBot
2
+ def get_teams
3
+ @teams ||= {}
4
+ teams_file = config.file_path.gsub(".rb", "_teams.yaml")
5
+ if File.exist?(teams_file)
6
+ if !defined?(@datetime_teams_file) or @datetime_teams_file != File.mtime(teams_file)
7
+ require 'yaml'
8
+ teams = @teams
9
+ 10.times do
10
+ teams = YAML.load(File.read(teams_file))
11
+ if teams.is_a?(Hash)
12
+ break
13
+ else
14
+ sleep (0.1*(rand(2)+1))
15
+ end
16
+ end
17
+ @teams = teams unless teams.is_a?(FalseClass)
18
+ @datetime_teams_file = File.mtime(teams_file)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ class SlackSmartBot
2
+ def get_vacations
3
+ @vacations ||= {}
4
+ vacations_file = config.file_path.gsub(".rb", "_vacations.yaml")
5
+ if File.exist?(vacations_file)
6
+ if !defined?(@datetime_vacations_file) or @datetime_vacations_file != File.mtime(vacations_file)
7
+ require 'yaml'
8
+ vacations = @vacations
9
+ 10.times do
10
+ vacations = YAML.load(File.read(vacations_file))
11
+ if vacations.is_a?(Hash)
12
+ break
13
+ else
14
+ sleep (0.1*(rand(2)+1))
15
+ end
16
+ end
17
+ @vacations = vacations unless vacations.is_a?(FalseClass)
18
+ @datetime_vacations_file = File.mtime(vacations_file)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,12 +1,28 @@
1
1
  class SlackSmartBot
2
- def has_access?(method, user=nil)
3
- user = Thread.current[:user] if user.nil?
4
- if config[:allow_access].key?(method) and !config[:allow_access][method].include?(user.name) and !config[:allow_access][method].include?(user.id) and
5
- (!user.key?(:enterprise_user) or ( user.key?(:enterprise_user) and !config[:allow_access][method].include?(user[:enterprise_user].id)))
6
- respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
7
- return false
2
+ def has_access?(method, user = nil)
3
+ user = Thread.current[:user] if user.nil?
4
+ if config[:allow_access].key?(method) and !config[:allow_access][method].include?(user.name) and !config[:allow_access][method].include?(user.id) and
5
+ (!user.key?(:enterprise_user) or (user.key?(:enterprise_user) and !config[:allow_access][method].include?(user[:enterprise_user].id)))
6
+ respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{config.admins.join(">, <@")}>"
7
+ return false
8
+ else
9
+ if Thread.current[:typem] == :on_call
10
+ channel = Thread.current[:dchannel]
11
+ elsif Thread.current[:using_channel].to_s == ""
12
+ channel = Thread.current[:dest]
13
+ else
14
+ channel = Thread.current[:using_channel]
15
+ end
16
+ if !@access_channels.key?(channel) or !@access_channels[channel].key?(method.to_s) or @access_channels[channel][method.to_s].include?(user.name)
17
+ return true
18
+ else
19
+ if @admins_channels.key?(channel) and !@admins_channels[channel].empty?
20
+ respond "You don't have access to use this command, please contact an Admin to be able to use it: <@#{@admins_channels[channel].join(">, <@")}>"
8
21
  else
9
- return true
10
- end
22
+ respond "You don't have access to use this command, please contact an Admin to be able to use it."
23
+ end
24
+ return false
25
+ end
11
26
  end
12
- end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ class SlackSmartBot
2
+ def is_admin?(from=nil)
3
+ if from.nil?
4
+ user = Thread.current[:user]
5
+ from = user.name
6
+ end
7
+
8
+ if (Thread.current[:dchannel].to_s!='' and !@channels_creator.key?(Thread.current[:dchannel])) or
9
+ (Thread.current[:dest].to_s!='' and Thread.current[:dest][0]!='D' and !@channels_creator.key?(Thread.current[:dest])) or
10
+ (Thread.current[:using_channel].to_s!='' and !@channels_creator.key?(:using_channel))
11
+ get_channels_name_and_id()
12
+ end
13
+
14
+ if config.masters.include?(from) or
15
+ config.admins.include?(from) or
16
+ (Thread.current[:typem] == :on_call and @admins_channels.key?(Thread.current[:dchannel]) and @admins_channels[Thread.current[:dchannel]].include?(from)) or
17
+ (Thread.current[:using_channel].to_s == '' and @admins_channels.key?(Thread.current[:dest]) and @admins_channels[Thread.current[:dest]].include?(from)) or
18
+ (@admins_channels.key?(Thread.current[:using_channel]) and @admins_channels[Thread.current[:using_channel]].include?(from)) or
19
+ (Thread.current[:using_channel].to_s=='' and @channels_creator.key?(Thread.current[:dest]) and from == @channels_creator[Thread.current[:dest]]) or
20
+ (Thread.current[:typem] == :on_call and @channels_creator.key?(Thread.current[:dchannel]) and from == @channels_creator[Thread.current[:dchannel]]) or
21
+ (@channels_creator.key?(Thread.current[:using_channel]) and from == @channels_creator[Thread.current[:using_channel]])
22
+ return true
23
+ else
24
+ return false
25
+ end
26
+ end
27
+ end
@@ -1,47 +1,57 @@
1
1
  class SlackSmartBot
2
+ def save_stats(method, data: {})
3
+ if has_access?(method, Thread.current[:user])
4
+ if config.stats
5
+ begin
6
+ require "csv"
7
+ if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
8
+ CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", "wb") do |csv|
9
+ csv << ["date", "bot_channel", "bot_channel_id", "dest_channel", "dest_channel_id", "type_message", "user_name", "user_id", "text", "command", "files", "time_zone"]
10
+ end
11
+ end
12
+ if data.empty?
13
+ data = {
14
+ dest: Thread.current[:dest],
15
+ typem: Thread.current[:typem],
16
+ user: Thread.current[:user],
17
+ files: Thread.current[:files?],
18
+ command: Thread.current[:command],
19
+ routine: Thread.current[:routine],
20
+ }
21
+ end
22
+ if method.to_s == "ruby_code" and data.files
23
+ command_txt = "ruby"
24
+ else
25
+ command_txt = data.command
26
+ end
27
+ command_txt.gsub!(/```.+```/m, "```CODE```")
28
+ command_txt = "#{command_txt[0..99]}..." if command_txt.size > 100
2
29
 
3
- def save_stats(method, data: {})
4
- if config.stats
5
- begin
6
- require 'csv'
7
- if !File.exist?("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log")
8
- CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", 'wb') do |csv|
9
- csv << ['date','bot_channel', 'bot_channel_id', 'dest_channel', 'dest_channel_id', 'type_message', 'user_name', 'user_id', 'text', 'command', 'files']
10
- end
11
- end
12
- if data.empty?
13
- data = {
14
- dest: Thread.current[:dest],
15
- typem: Thread.current[:typem],
16
- user: Thread.current[:user],
17
- files: Thread.current[:files?],
18
- command: Thread.current[:command],
19
- routine: Thread.current[:routine]
20
- }
21
- end
22
- if method.to_s == 'ruby_code' and data.files
23
- command_txt = 'ruby'
24
- else
25
- command_txt = data.command
26
- end
27
- command_txt.gsub!(/```.+```/m,'```CODE```')
28
- command_txt = "#{command_txt[0..99]}..." if command_txt.size > 100
30
+ if data.routine
31
+ user_name = "routine/#{data.user.name}"
32
+ user_id = "routine/#{data.user.id}"
33
+ else
34
+ user_name = data.user.name
35
+ user_id = data.user.id
36
+ end
37
+ user_info = @users.select { |u| u.id == user_id or (u.key?(:enterprise_user) and u.enterprise_user.id == user_id) }[-1]
38
+ if user_info.nil? or user_info.is_app_user or user_info.is_bot
39
+ time_zone = ''
40
+ else
41
+ time_zone = user_info.tz_label
42
+ end
29
43
 
30
- if data.routine
31
- user_name = "routine/#{data.user.name}"
32
- user_id = "routine/#{data.user.id}"
33
- else
34
- user_name = data.user.name
35
- user_id = data.user.id
36
- end
37
- CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", "a+") do |csv|
38
- csv << [Time.now, config.channel, @channel_id, @channels_name[data.dest], data.dest, data.typem, user_name, user_id, command_txt, method, data.files]
39
- end
40
- rescue Exception => exception
41
- @logger.fatal "There was a problem on the stats"
42
- @logger.fatal exception
43
- end
44
+ CSV.open("#{config.stats_path}.#{Time.now.strftime("%Y-%m")}.log", "a+") do |csv|
45
+ csv << [Time.now, config.channel, @channel_id, @channels_name[data.dest], data.dest, data.typem, user_name, user_id, command_txt, method, data.files, time_zone]
46
+ end
47
+ rescue Exception => exception
48
+ @logger.fatal "There was a problem on the stats"
49
+ @logger.fatal exception
44
50
  end
51
+ end
52
+ else
53
+ sleep 0.2
54
+ Thread.exit
45
55
  end
46
-
47
- end
56
+ end
57
+ end
@@ -7,12 +7,23 @@ class SlackSmartBot
7
7
  CSV.open("#{config.path}/status/#{config.channel}_status.csv", "a+") do |csv|
8
8
  csv << [Time.now.strftime("%Y/%m/%d"), Time.now.strftime("%H:%M:%S"), status, status_id, message]
9
9
  end
10
+ if defined?(@channels_list) #wait until the 'client' started
11
+ channel_info = @channels_list.select { |c| c.id == @channel_id}[-1]
12
+ if channel_info.nil? or channel_info.is_private
13
+ channel_link = "##{config.channel}"
14
+ else
15
+ channel_link = "<##{@channel_id}|#{config.channel}>"
16
+ end
17
+ else
18
+ channel_link = "##{config.channel}"
19
+ end
20
+
10
21
  if status_id == :disconnected
11
22
  Thread.new do
12
23
  sleep 50
13
24
  @logger.info "check disconnection 50 scs later #{@last_notified_status_id}"
14
25
  unless @last_notified_status_id == :connected
15
- respond ":red_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* is down. An admin will take a look. <@#{config.admins.join(">, <@")}>", config.status_channel
26
+ respond ":red_circle: The *SmartBot* on *#{channel_link}* is down. An admin will take a look. <@#{config.admins.join(">, <@")}>", config.status_channel
16
27
  end
17
28
  end
18
29
  end
@@ -22,27 +33,31 @@ class SlackSmartBot
22
33
  if (Time.now-@last_status_change) > 20 or !defined?(@last_notified_status_id)
23
34
  if status_id == :connected
24
35
  if defined?(@last_notified_status_id)
25
- m = ":exclamation: :large_green_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* was not available for #{(Time.now-@last_status_change).round(0)} secs. *Now it is up and running again.*"
36
+ m = ":exclamation: :large_green_circle: The *SmartBot* on *#{channel_link}* was not available for #{(Time.now-@last_status_change).round(0)} secs. *Now it is up and running again.*"
26
37
  else
27
- m = ":large_green_circle: The *SmartBot* on *<##{@channel_id}|#{config.channel}>* is up and running again."
38
+ m = ":large_green_circle: The *SmartBot* on *#{channel_link}* is up and running again."
28
39
  end
29
40
  end
30
41
  end
31
42
  if status_id == :paused
32
- m = ":red_circle: #{message} *<##{@channel_id}|#{config.channel}>*"
43
+ m = ":red_circle: #{message} *#{channel_link}*"
33
44
  elsif status_id == :started
34
- m = ":large_green_circle: #{message} *<##{@channel_id}|#{config.channel}>*"
45
+ m = ":large_green_circle: #{message} *#{channel_link}*"
35
46
  elsif status_id == :killed or status_id == :exited
36
47
  m = ":red_circle: #{message}"
37
48
  elsif config.on_master_bot and status_id == :maintenance_on
38
- m = ":red_circle: The *SmartBot* is on maintenance so not possible to attend any request."
49
+ if message.to_s == "Sorry I'm on maintenance so I cannot attend your request."
50
+ m = ":red_circle: The *SmartBot* is on maintenance so not possible to attend any request."
51
+ else
52
+ m = ":red_circle: #{message}"
53
+ end
39
54
  elsif config.on_master_bot and status_id == :maintenance_off
40
55
  m = ":large_green_circle: The *SmartBot* is up and running again."
41
56
  end
42
57
  @last_status_change = Time.now
43
58
  @last_notified_status_id = status_id
44
59
  unless m == ''
45
- respond m, config.status_channel
60
+ respond eval("\"" + m + "\""), config.status_channel
46
61
  end
47
62
  end
48
63
 
@@ -0,0 +1,8 @@
1
+ class SlackSmartBot
2
+
3
+ def update_access_channels()
4
+ file = File.open("#{config.path}/rules/#{@channel_id}/access_channels.rb", "w")
5
+ file.write (@access_channels.inspect)
6
+ file.close
7
+ end
8
+ end
@@ -0,0 +1,25 @@
1
+ class SlackSmartBot
2
+
3
+ def update_admins_channels()
4
+
5
+ require 'yaml'
6
+ admins_file = "#{config.path}/rules/#{@channel_id}/admins_channels.yaml"
7
+
8
+ if File.exist?(admins_file.gsub(".yaml", ".rb")) #backwards compatible
9
+ file_conf = IO.readlines(admins_file.gsub(".yaml", ".rb")).join
10
+ if file_conf.to_s() == ""
11
+ @admins_channels = {}
12
+ else
13
+ @admins_channels = eval(file_conf)
14
+ end
15
+ File.open(admins_file, 'w') {|file| file.write(@admins_channels.to_yaml) }
16
+ File.delete(admins_file.gsub(".yaml", ".rb"))
17
+ end
18
+
19
+ File.open(admins_file, 'w') {|file|
20
+ file.flock(File::LOCK_EX)
21
+ file.write(@admins_channels.to_yaml)
22
+ file.flock(File::LOCK_UN)
23
+ }
24
+ end
25
+ end
@@ -1,11 +1,32 @@
1
1
  class SlackSmartBot
2
2
  def update_bots_file
3
- file = File.open(config.file_path.gsub(".rb", "_bots.rb"), "w")
4
- bots_created = @bots_created.dup
5
- bots_created.each { |k, v|
6
- v[:thread] = ""
7
- }
8
- file.write bots_created.inspect
9
- file.close
3
+ bots_file = config.file_path.gsub(".rb", "_bots.yaml")
4
+
5
+ if File.exist?(config.file_path.gsub(".rb", "_bots.rb")) #backwards compatible
6
+ file_conf = IO.readlines(config.file_path.gsub(".rb", "_bots.rb")).join
7
+ if file_conf.to_s() == ""
8
+ @bots_created = {}
9
+ else
10
+ @bots_created = eval(file_conf)
11
+ end
12
+ File.open(bots_file, 'w') {|file|
13
+ file.flock(File::LOCK_EX)
14
+ file.write(@bots_created.to_yaml)
15
+ file.flock(File::LOCK_UN)
16
+ }
17
+ File.delete(config.file_path.gsub(".rb", "_bots.rb"))
18
+ else
19
+ #not possible to use @bots_created.deep_copy since one of the fields contains a thread
20
+ bots_created = {}
21
+ @bots_created.each do |k,v|
22
+ bots_created[k] = v.dup
23
+ bots_created[k][:thread] = ''
24
+ end
25
+ File.open(bots_file, 'w') {|file|
26
+ file.flock(File::LOCK_EX)
27
+ file.write(bots_created.to_yaml)
28
+ file.flock(File::LOCK_UN)
29
+ }
30
+ end
10
31
  end
11
32
  end
@@ -1,8 +1,11 @@
1
1
  class SlackSmartBot
2
-
3
2
  def update_repls(channel = @channel_id)
4
- file = File.open("#{config.path}/repl/repls_#{channel}.rb", "w")
5
- file.write (@repls.inspect)
6
- file.close
3
+ require 'yaml'
4
+ repl_file = "#{config.path}/repl/repls_#{channel}.yaml"
5
+ File.open(repl_file, 'w') {|file|
6
+ file.flock(File::LOCK_EX)
7
+ file.write(@repls.to_yaml)
8
+ file.flock(File::LOCK_UN)
9
+ }
7
10
  end
8
11
  end