slack-smart-bot 0.9.6 → 1.0.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -1
  3. data/README.md +80 -175
  4. data/lib/slack-smart-bot.rb +95 -1276
  5. data/lib/slack-smart-bot_rules.rb +50 -69
  6. data/lib/slack/smart-bot/comm.rb +197 -0
  7. data/lib/slack/smart-bot/commands/general/bot_help.rb +74 -0
  8. data/lib/slack/smart-bot/commands/general/bot_status.rb +41 -0
  9. data/lib/slack/smart-bot/commands/general/bye_bot.rb +17 -0
  10. data/lib/slack/smart-bot/commands/general/hi_bot.rb +24 -0
  11. data/lib/slack/smart-bot/commands/general/stop_using_rules.rb +44 -0
  12. data/lib/slack/smart-bot/commands/general/use_rules.rb +48 -0
  13. data/lib/slack/smart-bot/commands/on_bot/add_shortcut.rb +64 -0
  14. data/lib/slack/smart-bot/commands/on_bot/admin/add_routine.rb +87 -0
  15. data/lib/slack/smart-bot/commands/on_bot/admin/extend_rules.rb +63 -0
  16. data/lib/slack/smart-bot/commands/on_bot/admin/pause_bot.rb +21 -0
  17. data/lib/slack/smart-bot/commands/on_bot/admin/pause_routine.rb +26 -0
  18. data/lib/slack/smart-bot/commands/on_bot/admin/remove_routine.rb +28 -0
  19. data/lib/slack/smart-bot/commands/on_bot/admin/run_routine.rb +53 -0
  20. data/lib/slack/smart-bot/commands/on_bot/admin/see_routines.rb +57 -0
  21. data/lib/slack/smart-bot/commands/on_bot/admin/start_bot.rb +20 -0
  22. data/lib/slack/smart-bot/commands/on_bot/admin/start_routine.rb +27 -0
  23. data/lib/slack/smart-bot/commands/on_bot/admin/stop_using_rules_on.rb +30 -0
  24. data/lib/slack/smart-bot/commands/on_bot/delete_shortcut.rb +41 -0
  25. data/lib/slack/smart-bot/commands/on_bot/ruby_code.rb +48 -0
  26. data/lib/slack/smart-bot/commands/on_bot/see_shortcuts.rb +32 -0
  27. data/lib/slack/smart-bot/commands/on_extended/bot_rules.rb +37 -0
  28. data/lib/slack/smart-bot/commands/on_master/admin/kill_bot_on_channel.rb +38 -0
  29. data/lib/slack/smart-bot/commands/on_master/admin_master/exit_bot.rb +42 -0
  30. data/lib/slack/smart-bot/commands/on_master/admin_master/notify_message.rb +35 -0
  31. data/lib/slack/smart-bot/commands/on_master/create_bot.rb +94 -0
  32. data/lib/slack/smart-bot/listen.rb +36 -0
  33. data/lib/slack/smart-bot/process.rb +169 -0
  34. data/lib/slack/smart-bot/process_first.rb +201 -0
  35. data/lib/slack/smart-bot/treat_message.rb +139 -0
  36. data/lib/slack/smart-bot/utils.rb +299 -0
  37. metadata +71 -5
@@ -0,0 +1,35 @@
1
+ class SlackSmartBot
2
+ # helpmaster: ----------------------------------------------
3
+ # helpmaster: `notify MESSAGE`
4
+ # helpmaster: `notify all MESSAGE`
5
+ # helpmaster: `notify #CHANNEL_NAME MESSAGE`
6
+ # helpmaster: It will send a notification message to all bot channels
7
+ # helpmaster: It will send a notification message to all channels the bot joined and private conversations with the bot
8
+ # helpmaster: It will send a notification message to the specified channel and to its extended channels
9
+ # helpmaster: Only works if you are on Master channel and you are a master admin user
10
+ # helpmaster:
11
+ def notify_message(dest, from, where, message)
12
+ if ON_MASTER_BOT
13
+ if ADMIN_USERS.include?(from) #admin user
14
+ if where.nil? #not all and not channel
15
+ @bots_created.each do |k, v|
16
+ respond message, k
17
+ end
18
+ respond "Bot channels have been notified", dest
19
+ elsif where == "all" #all
20
+ myconv = client.web_client.users_conversations(exclude_archived: true, limit: 100, types: "im, public_channel,private_channel").channels
21
+ myconv.each do |c|
22
+ respond message, c.id unless c.name == MASTER_CHANNEL
23
+ end
24
+ respond "Channels and users have been notified", dest
25
+ else #channel
26
+ respond message, where
27
+ @bots_created[where][:extended].each do |ch|
28
+ respond message, @channels_id[ch]
29
+ end
30
+ respond "Bot channel and extended channels have been notified", dest
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,94 @@
1
+ class SlackSmartBot
2
+ # helpmaster: ----------------------------------------------
3
+ # helpmaster: `create bot on CHANNEL_NAME`
4
+ # helpmaster: `create cloud bot on CHANNEL_NAME`
5
+ # helpmaster: creates a new bot on the channel specified
6
+ # helpmaster: it will work only if you are on Master channel
7
+ # helpmaster: the admins will be the master admins, the creator of the bot and the creator of the channel
8
+ # helpmaster: follow the instructions in case creating cloud bots
9
+ # helpmaster:
10
+ def create_bot(dest, from, cloud, channel)
11
+ if ON_MASTER_BOT
12
+ get_channels_name_and_id() unless @channels_name.keys.include?(channel) or @channels_id.keys.include?(channel)
13
+ channel_id = nil
14
+ if @channels_name.key?(channel) #it is an id
15
+ channel_id = channel
16
+ channel = @channels_name[channel_id]
17
+ elsif @channels_id.key?(channel) #it is a channel name
18
+ channel_id = @channels_id[channel]
19
+ end
20
+ #todo: add pagination for case more than 1000 channels on the workspace
21
+ channels = client.web_client.conversations_list(
22
+ types: "private_channel,public_channel",
23
+ limit: "1000",
24
+ exclude_archived: "true",
25
+ ).channels
26
+ channel_found = channels.detect { |c| c.name == channel }
27
+ members = client.web_client.conversations_members(channel: @channels_id[channel]).members unless channel_found.nil?
28
+
29
+ if channel_id.nil?
30
+ respond "There is no channel with that name: #{channel}, please be sure is written exactly the same", dest
31
+ elsif channel == MASTER_CHANNEL
32
+ respond "There is already a bot in this channel: #{channel}", dest
33
+ elsif @bots_created.keys.include?(channel_id)
34
+ respond "There is already a bot in this channel: #{channel}, kill it before", dest
35
+ elsif config[:nick_id] != channel_found.creator and !members.include?(config[:nick_id])
36
+ respond "You need to add first to the channel the smart bot user: #{config[:nick]}", dest
37
+ else
38
+ if channel_id != config[:channel]
39
+ begin
40
+ rules_file = "slack-smart-bot_rules_#{channel_id}_#{from.gsub(" ", "_")}.rb"
41
+ if defined?(RULES_FOLDER)
42
+ rules_file = RULES_FOLDER + rules_file
43
+ else
44
+ Dir.mkdir("rules") unless Dir.exist?("rules")
45
+ Dir.mkdir("rules/#{channel_id}") unless Dir.exist?("rules/#{channel_id}")
46
+ rules_file = "./rules/#{channel_id}/" + rules_file
47
+ end
48
+ default_rules = (__FILE__).gsub(/slack\/smart-bot\/commands\/on_master\/create_bot\.rb$/, "slack-smart-bot_rules.rb")
49
+ File.delete(rules_file) if File.exist?(rules_file)
50
+ FileUtils.copy_file(default_rules, rules_file) unless File.exist?(rules_file)
51
+ admin_users = Array.new()
52
+ creator_info = client.web_client.users_info(user: channel_found.creator)
53
+ admin_users = [from, creator_info.user.name] + MASTER_USERS
54
+ admin_users.uniq!
55
+ @logger.info "ruby #{$0} \"#{channel}\" \"#{admin_users.join(",")}\" \"#{rules_file}\" on"
56
+
57
+ if cloud
58
+ respond "Copy the bot folder to your cloud location and run `ruby #{$0} \"#{channel}\" \"#{admin_users.join(",")}\" \"#{rules_file}\" on&`", dest
59
+ else
60
+ t = Thread.new do
61
+ `ruby #{$0} \"#{channel}\" \"#{admin_users.join(",")}\" \"#{rules_file}\" on`
62
+ end
63
+ end
64
+ @bots_created[channel_id] = {
65
+ creator_name: from,
66
+ channel_id: channel_id,
67
+ channel_name: @channels_name[channel_id],
68
+ status: :on,
69
+ created: Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")[0..18],
70
+ rules_file: rules_file,
71
+ admins: admin_users.join(","),
72
+ extended: [],
73
+ cloud: cloud,
74
+ thread: t,
75
+ }
76
+ respond "The bot has been created on channel: #{channel}. Rules file: #{File.basename rules_file}. Admins: #{admin_users.join(", ")}", dest
77
+ update_bots_file()
78
+ rescue Exception => stack
79
+ @logger.fatal stack
80
+ message = "Problem creating the bot on channel #{channel}. Error: <#{stack}>."
81
+ @logger.error message
82
+ respond message, dest
83
+ end
84
+ else
85
+ respond "There is already a bot in this channel: #{channel}, and it is the Master Channel!", dest
86
+ end
87
+ end
88
+ else
89
+ @logger.info MASTER_CHANNEL
90
+ @logger.info @channel_id.inspect
91
+ respond "Sorry I cannot create bots from this channel, please visit the master channel: <##{@master_bot_id}>", dest
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,36 @@
1
+ class SlackSmartBot
2
+ def listen
3
+ @salutations = [config[:nick], "<@#{config[:nick_id]}>", "bot", "smart"]
4
+ @pings = []
5
+ get_bots_created()
6
+ client.on :message do |data|
7
+ unless data.user == "USLACKBOT"
8
+ treat_message(data)
9
+ end
10
+ end
11
+
12
+ restarts = 0
13
+ started = false
14
+ while restarts < 200 and !started
15
+ begin
16
+ @logger.info "Bot starting: #{config.inspect}"
17
+ client.start!
18
+ rescue Slack::RealTime::Client::ClientAlreadyStartedError
19
+ @logger.info "ClientAlreadyStarted so we continue with execution"
20
+ started = true
21
+ rescue Exception => e
22
+ started = false
23
+ restarts += 1
24
+ if restarts < 200
25
+ @logger.info "*" * 50
26
+ @logger.fatal "Rescued on starting: #{e.inspect}"
27
+ @logger.info "Waiting 60 seconds to retry. restarts: #{restarts}"
28
+ puts "#{Time.now}: Not able to start client. Waiting 60 seconds to retry: #{config.inspect}"
29
+ sleep 60
30
+ else
31
+ exit!
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,169 @@
1
+ require_relative "commands/general/hi_bot"
2
+ require_relative "commands/general/bye_bot"
3
+ require_relative "commands/general/bot_help"
4
+ require_relative "commands/on_bot/ruby_code"
5
+ require_relative "commands/general/use_rules"
6
+ require_relative "commands/general/stop_using_rules"
7
+ require_relative "commands/on_master/admin_master/exit_bot"
8
+ require_relative "commands/on_master/admin_master/notify_message"
9
+ require_relative "commands/on_master/admin/kill_bot_on_channel"
10
+ require_relative "commands/on_master/create_bot"
11
+ require_relative "commands/on_bot/admin/add_routine"
12
+ require_relative "commands/on_bot/admin/start_bot"
13
+ require_relative "commands/on_bot/admin/pause_bot"
14
+ require_relative "commands/on_bot/admin/remove_routine"
15
+ require_relative "commands/on_bot/admin/run_routine"
16
+ require_relative "commands/on_bot/admin/pause_routine"
17
+ require_relative "commands/on_bot/admin/start_routine"
18
+ require_relative "commands/on_bot/admin/see_routines"
19
+ require_relative "commands/on_bot/admin/extend_rules"
20
+ require_relative "commands/on_bot/admin/stop_using_rules_on"
21
+ require_relative "commands/general/bot_status"
22
+ require_relative "commands/on_bot/add_shortcut"
23
+ require_relative "commands/on_bot/delete_shortcut"
24
+ require_relative "commands/on_bot/see_shortcuts"
25
+ require_relative "commands/on_extended/bot_rules"
26
+
27
+ class SlackSmartBot
28
+ def process(user, command, dest, dchannel, rules_file, typem, files)
29
+ from = user.name
30
+ if user.profile.display_name.to_s.match?(/\A\s*\z/)
31
+ user.profile.display_name = user.profile.real_name
32
+ end
33
+ display_name = user.profile.display_name
34
+ processed = true
35
+
36
+ on_demand = false
37
+ if command.match(/^@?(#{config[:nick]}):*\s+(.+)/im) or
38
+ command.match(/^()!(.+)/im) or
39
+ command.match(/^()<@#{config[:nick_id]}>\s+(.+)/im)
40
+ command = $2
41
+ on_demand = true
42
+ end
43
+
44
+ #todo: check :on_pg in this case
45
+ if typem == :on_master or typem == :on_bot or typem == :on_pg or typem == :on_dm
46
+ case command
47
+
48
+ when /^\s*(Hello|Hallo|Hi|Hola|What's\sup|Hey|Hæ)\s(#{@salutations.join("|")})\s*$/i
49
+ hi_bot(user, dest, dchannel, from, display_name)
50
+ when /^\s*(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Adeu)\s(#{@salutations.join("|")})\s*$/i
51
+ bye_bot(dest, from, display_name)
52
+ when /^\s*bot\s+(rules|help)\s*(.+)?$/i, /^bot,? what can I do/i
53
+ $1.to_s.match?(/rules/i) ? specific = true : specific = false
54
+ help_command = $2
55
+
56
+ bot_help(user, from, dest, dchannel, specific, help_command, rules_file)
57
+ when /^\s*use\s+(rules\s+)?(from\s+)?<#C\w+\|(.+)>\s*$/i, /^use\s+(rules\s+)?(from\s+)?([^\s]+\s*$)/i
58
+ channel = $3
59
+ use_rules(dest, channel, user, dchannel)
60
+ when /^\s*stop using rules (from\s+)<#\w+\|(.+)>/i, /^stop using rules (from\s+)(.+)/i
61
+ channel = $2
62
+ stop_using_rules(dest, channel, user, dchannel)
63
+ when /^\s*extend\s+rules\s+(to\s+)<#C\w+\|(.+)>/i, /^extend\s+rules\s+(to\s+)(.+)/i,
64
+ /^\s*use\s+rules\s+(on\s+)<#C\w+\|(.+)>/i, /^use\s+rules\s+(on\s+)(.+)/i
65
+ channel = $2
66
+ extend_rules(dest, user, from, channel, typem)
67
+ when /^\s*stop using rules (on\s+)<#\w+\|(.+)>/i, /^stop using rules (on\s+)(.+)/i
68
+ channel = $2
69
+ stop_using_rules_on(dest, user, from, channel, typem)
70
+ when /^\s*exit\sbot\s*$/i, /^quit\sbot\s*$/i, /^close\sbot\s*$/i
71
+ exit_bot(command, from, dest, display_name)
72
+ when /^\s*start\s(this\s)?bot$/i
73
+ start_bot(dest, from)
74
+ when /^\s*pause\s(this\s)?bot$/i
75
+ pause_bot(dest, from)
76
+ when /^\s*bot\sstatus/i
77
+ bot_status(dest, from)
78
+ when /\Anotify\s+<#(C\w+)\|.+>\s+(.+)\s*\z/im, /\Anotify\s+(all)?\s*(.+)\s*\z/im
79
+ where = $1
80
+ message = $2
81
+ notify_message(dest, from, where, message)
82
+ when /^\s*create\s+(cloud\s+)?bot\s+on\s+<#C\w+\|(.+)>\s*/i, /^create\s+(cloud\s+)?bot\s+on\s+(.+)\s*/i
83
+ cloud = !$1.nil?
84
+ channel = $2
85
+ create_bot(dest, from, cloud, channel)
86
+ when /^\s*kill\sbot\son\s<#C\w+\|(.+)>\s*$/i, /^kill\sbot\son\s(.+)\s*$/i
87
+ channel = $1
88
+ kill_bot_on_channel(dest, from, channel)
89
+ when /^\s*(add|create)\s+routine\s+(\w+)\s+(every)\s+(\d+)\s*(days|hours|minutes|seconds|mins|min|secs|sec|d|h|m|s)\s*(\s.+)?\s*$/i,
90
+ /^\s*(add|create)\s+routine\s+(\w+)\s+(at)\s+(\d+:\d+:?\d+?)\s*()(\s.+)?\s*$/i
91
+ name = $2.downcase
92
+ type = $3
93
+ number_time = $4
94
+ period = $5
95
+ command_to_run = $6
96
+ add_routine(dest, from, user, name, type, number_time, period, command_to_run, files)
97
+ when /^\s*(kill|delete|remove)\s+routine\s+(\w+)\s*$/i
98
+ name = $2.downcase
99
+ remove_routine(dest, from, name)
100
+ when /^\s*(run|execute)\s+routine\s+(\w+)\s*$/i
101
+ name = $2.downcase
102
+ run_routine(dest, from, name)
103
+ when /^\s*pause\s+routine\s+(\w+)\s*$/i
104
+ name = $1.downcase
105
+ pause_routine(dest, from, name)
106
+ when /^\s*start\s+routine\s+(\w+)\s*$/i
107
+ name = $1.downcase
108
+ start_routine(dest, from, name)
109
+ when /^\s*see\s+(all\s+)?routines\s*$/i
110
+ all = $1.to_s != ""
111
+ see_routines(dest, from, user, all)
112
+ else
113
+ processed = false
114
+ end
115
+ else
116
+ processed = false
117
+ end
118
+
119
+ # only when :on and (listening or on demand or direct message)
120
+ if @status == :on and
121
+ (@questions.keys.include?(from) or
122
+ (@listening.include?(from) and typem != :on_extended) or
123
+ typem == :on_dm or typem == :on_pg or on_demand)
124
+ processed2 = true
125
+
126
+ case command
127
+
128
+ # bot rules for extended channels
129
+ when /^bot\s+rules\s*(.+)?$/i
130
+ help_command = $1
131
+ bot_rules(dest, help_command, typem, rules_file, from)
132
+ when /^\s*(add\s)?shortcut\s(for\sall)?\s*(.+)\s*:\s*(.+)/i, /^(add\s)sc\s(for\sall)?\s*(.+)\s*:\s*(.+)/i
133
+ for_all = $2
134
+ shortcut_name = $3.to_s.downcase
135
+ command_to_run = $4
136
+ add_shortcut(dest, from, typem, for_all, shortcut_name, command, command_to_run)
137
+ when /^\s*delete\s+shortcut\s+(.+)/i, /^delete\s+sc\s+(.+)/i
138
+ shortcut = $1.to_s.downcase
139
+ delete_shortcut(dest, from, shortcut, typem, command)
140
+ when /^\s*see\sshortcuts/i, /^see\ssc/i
141
+ see_shortcuts(dest, from, typem)
142
+
143
+ #kept to be backwards compatible
144
+ when /^\s*id\schannel\s<#C\w+\|(.+)>\s*/i, /^id channel (.+)/
145
+ unless typem == :on_extended
146
+ channel_name = $1
147
+ get_channels_name_and_id()
148
+ if @channels_id.keys.include?(channel_name)
149
+ respond "the id of #{channel_name} is #{@channels_id[channel_name]}", dest
150
+ else
151
+ respond "channel: #{channel_name} not found", dest
152
+ end
153
+ end
154
+ when /^\s*ruby\s(.+)/im, /^\s*code\s(.+)/im
155
+ code = $1
156
+ code.gsub!("\\n", "\n")
157
+ code.gsub!("\\r", "\r")
158
+ @logger.info code
159
+ ruby_code(dest, code, rules_file)
160
+ else
161
+ processed2 = false
162
+ end #of case
163
+
164
+ processed = true if processed or processed2
165
+ end
166
+
167
+ return processed
168
+ end
169
+ end
@@ -0,0 +1,201 @@
1
+ class SlackSmartBot
2
+ def process_first(user, text, dest, dchannel, typem, files)
3
+ nick = user.name
4
+ rules_file = ""
5
+
6
+ if typem == :on_call
7
+ rules_file = RULES_FILE
8
+ elsif dest[0] == "C" or dest[0] == "G" # on a channel or private channel
9
+ rules_file = RULES_FILE
10
+
11
+ if @rules_imported.key?(user.id) and @rules_imported[user.id].key?(dchannel)
12
+ unless @bots_created.key?(@rules_imported[user.id][dchannel])
13
+ get_bots_created()
14
+ end
15
+ if @bots_created.key?(@rules_imported[user.id][dchannel])
16
+ rules_file = @bots_created[@rules_imported[user.id][dchannel]][:rules_file]
17
+ end
18
+ end
19
+ elsif dest[0] == "D" and @rules_imported.key?(user.id) and @rules_imported[user.id].key?(user.id) #direct message
20
+ unless @bots_created.key?(@rules_imported[user.id][user.id])
21
+ get_bots_created()
22
+ end
23
+ if @bots_created.key?(@rules_imported[user.id][user.id])
24
+ rules_file = @bots_created[@rules_imported[user.id][user.id]][:rules_file]
25
+ end
26
+ end
27
+
28
+ if nick == config[:nick] #if message is coming from the bot
29
+ begin
30
+ case text
31
+ when /^Bot has been (closed|killed) by/i
32
+ if CHANNEL == @channels_name[dchannel]
33
+ @logger.info "#{nick}: #{text}"
34
+ exit!
35
+ end
36
+ when /^Changed status on (.+) to :(.+)/i
37
+ channel_name = $1
38
+ status = $2
39
+ if ON_MASTER_BOT or CHANNEL == channel_name
40
+ @bots_created[@channels_id[channel_name]][:status] = status.to_sym
41
+ update_bots_file()
42
+ if CHANNEL == channel_name
43
+ @logger.info "#{nick}: #{text}"
44
+ else #on master bot
45
+ @logger.info "Changed status on #{channel_name} to :#{status}"
46
+ end
47
+ end
48
+ when /extended the rules from (.+) to be used on (.+)\.$/i
49
+ from_name = $1
50
+ to_name = $2
51
+ if ON_MASTER_BOT and @bots_created[@channels_id[from_name]][:cloud]
52
+ @bots_created[@channels_id[from_name]][:extended] << to_name
53
+ @bots_created[@channels_id[from_name]][:extended].uniq!
54
+ update_bots_file()
55
+ end
56
+ when /removed the access to the rules of (.+) from (.+)\.$/i
57
+ from_name = $1
58
+ to_name = $2
59
+ if ON_MASTER_BOT and @bots_created[@channels_id[from_name]][:cloud]
60
+ @bots_created[@channels_id[from_name]][:extended].delete(to_name)
61
+ update_bots_file()
62
+ end
63
+ end
64
+
65
+ return :next #don't continue analyzing #jal
66
+ rescue Exception => stack
67
+ @logger.fatal stack
68
+ return :next #jal
69
+ end
70
+ end
71
+
72
+ #only for shortcuts
73
+ if text.match(/^@?(#{config[:nick]}):*\s+(.+)\s*/im) or
74
+ text.match(/^()!\s*(.+)\s*/im) or
75
+ text.match(/^()<@#{config[:nick_id]}>\s+(.+)\s*/im)
76
+ command = $2
77
+ addexcl = true
78
+ else
79
+ addexcl = false
80
+ command = text.downcase.lstrip.rstrip
81
+ end
82
+ if command.scan(/^(shortcut|sc)\s+([^:]+)\s*$/i).any? or
83
+ (@shortcuts.keys.include?(:all) and @shortcuts[:all].keys.include?(command)) or
84
+ (@shortcuts.keys.include?(nick) and @shortcuts[nick].keys.include?(command))
85
+ command = $2.downcase unless $2.nil?
86
+ if @shortcuts.keys.include?(nick) and @shortcuts[nick].keys.include?(command)
87
+ text = @shortcuts[nick][command].dup
88
+ elsif @shortcuts.keys.include?(:all) and @shortcuts[:all].keys.include?(command)
89
+ text = @shortcuts[:all][command].dup
90
+ else
91
+ respond "Shortcut not found", dest unless dest[0] == "C" and dchannel != dest #on extended channel
92
+ return :next #jal
93
+ end
94
+ text = "!" + text if addexcl and text[0] != "!"
95
+ end
96
+
97
+ command = text
98
+
99
+ begin
100
+ t = Thread.new do
101
+ begin
102
+ Thread.current[:dest] = dest
103
+ Thread.current[:user] = user
104
+ Thread.current[:command] = command
105
+ Thread.current[:rules_file] = rules_file
106
+ processed = process(user, command, dest, dchannel, rules_file, typem, files)
107
+ @logger.info "command: #{nick}> #{command}" if processed
108
+ on_demand = false
109
+ if command.match(/^@?(#{config[:nick]}):*\s+(.+)/im) or
110
+ command.match(/^()!(.+)/im) or
111
+ command.match(/^()<@#{config[:nick_id]}>\s+(.+)/im)
112
+ command = $2
113
+ Thread.current[:command] = command
114
+ on_demand = true
115
+ end
116
+ if @status == :on and
117
+ (@questions.keys.include?(nick) or
118
+ (@listening.include?(nick) and typem != :on_extended) or
119
+ dest[0] == "D" or on_demand)
120
+ @logger.info "command: #{nick}> #{command}" unless processed
121
+ #todo: verify this
122
+
123
+ if dest[0] == "C" or dest[0] == "G" or (dest[0] == "D" and typem == :on_call)
124
+ if typem != :on_call and @rules_imported.key?(user.id) and @rules_imported[user.id].key?(dchannel)
125
+ if @bots_created.key?(@rules_imported[user.id][dchannel])
126
+ if @bots_created[@rules_imported[user.id][dchannel]][:status] != :on
127
+ respond "The bot on that channel is not :on", dest
128
+ rules_file = ""
129
+ end
130
+ end
131
+ end
132
+ unless rules_file.empty?
133
+ begin
134
+ eval(File.new(rules_file).read) if File.exist?(rules_file)
135
+ rescue Exception => stack
136
+ @logger.fatal "ERROR ON RULES FILE: #{rules_file}"
137
+ @logger.fatal stack
138
+ end
139
+ if defined?(rules)
140
+ command[0] = "" if command[0] == "!"
141
+ command.gsub!(/^@\w+:*\s*/, "")
142
+ if method(:rules).parameters.size == 4
143
+ rules(user, command, processed, dest)
144
+ elsif method(:rules).parameters.size == 5
145
+ rules(user, command, processed, dest, files)
146
+ else
147
+ rules(user, command, processed, dest, files, rules_file)
148
+ end
149
+ else
150
+ @logger.warn "It seems like rules method is not defined"
151
+ end
152
+ end
153
+ elsif @rules_imported.key?(user.id) and @rules_imported[user.id].key?(user.id)
154
+ if @bots_created.key?(@rules_imported[user.id][user.id])
155
+ if @bots_created[@rules_imported[user.id][user.id]][:status] == :on
156
+ begin
157
+ eval(File.new(rules_file).read) if File.exist?(rules_file)
158
+ rescue Exception => stack
159
+ @logger.fatal "ERROR ON imported RULES FILE: #{rules_file}"
160
+ @logger.fatal stack
161
+ end
162
+ else
163
+ respond "The bot on <##{@rules_imported[user.id][user.id]}|#{@bots_created[@rules_imported[user.id][user.id]][:channel_name]}> is not :on", dest
164
+ rules_file = ""
165
+ end
166
+ end
167
+
168
+ unless rules_file.empty?
169
+ if defined?(rules)
170
+ command[0] = "" if command[0] == "!"
171
+ command.gsub!(/^@\w+:*\s*/, "")
172
+ if method(:rules).parameters.size == 4
173
+ rules(user, command, processed, dest)
174
+ elsif method(:rules).parameters.size == 5
175
+ rules(user, command, processed, dest, files)
176
+ else
177
+ rules(user, command, processed, dest, files, rules_file)
178
+ end
179
+ else
180
+ @logger.warn "It seems like rules method is not defined"
181
+ end
182
+ end
183
+ else
184
+ @logger.info "it is a direct message with no rules file selected so no rules file executed."
185
+ if command.match?(/^\s*bot\s+rules\s*$/i)
186
+ respond "No rules running. You can use the command `use rules from CHANNEL` to specify the rules you want to use on this private conversation.\n`bot help` to see available commands.", dest
187
+ end
188
+ unless processed
189
+ dont_understand(__FILE__, command, user, dest)
190
+ end
191
+ end
192
+ end
193
+ rescue Exception => stack
194
+ @logger.fatal stack
195
+ end
196
+ end
197
+ rescue => e
198
+ @logger.error "exception: #{e.inspect}"
199
+ end
200
+ end
201
+ end