hipchat_smart 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +249 -0
- data/lib/hipchat_smart.rb +652 -0
- data/lib/hipchat_smart_rules.rb +82 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: da292e2d66a6bbbf1edf2ebc2fd28232d3cfeb29
|
4
|
+
data.tar.gz: 62d4d3b1363829d97e3b867c2a973212011c1fe3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5e72a6e8782ced566bbbe365e95c281f8c7166e9898d538692c148ff466e0a2a8cbe45ef3c9db427d4aed01c04fc88528d1dba1f423e56902d8e470a630c87c
|
7
|
+
data.tar.gz: ef0691f01534b9e91394fec3bff846dd5d9612dc07ef17bc947d33b81b818cd968bbc58a8954a83363d23e68590003dabc78a2080c7c78a3b745cd31d982b42e
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Mario Ruiz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
# HipChat Smart
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/hipchat_smart.svg)](https://rubygems.org/gems/hipchat_smart)
|
4
|
+
|
5
|
+
Create a hipchat bot that is really smart and so easy to expand.
|
6
|
+
|
7
|
+
The main scope of this ruby gem is to be used internally in your company so teams can create team rooms with their own bot to help them on their daily work, almost everything is suitable to be automated!!
|
8
|
+
|
9
|
+
hipchat_smart can create bots on demand, create shortcuts, run ruby code... just on a chat room, you can access it just from your mobile phone if you want and run those tests you forgot to run, get the results, restart a server... no limits.
|
10
|
+
|
11
|
+
## Installation and configuration
|
12
|
+
|
13
|
+
$ gem install hipchat_smart
|
14
|
+
|
15
|
+
After you install it you will need just a couple of things to configure it.
|
16
|
+
|
17
|
+
Create a file like this on the folder you want:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
#jid of the room that will act like the master room, main room
|
21
|
+
MASTER_ROOM="1_my_master_room"
|
22
|
+
#names of the master users
|
23
|
+
MASTER_USERS=["Mario Ruiz Sanchez"]
|
24
|
+
|
25
|
+
require 'hipchat_smart'
|
26
|
+
|
27
|
+
settings = {
|
28
|
+
jid: 'bot_user_jid@your_company_hipchat_domain.com/bot',
|
29
|
+
nick: 'bot user name',
|
30
|
+
password: "xxxxxxxxxxxx",
|
31
|
+
token: 'xxxxxxxxxxxxxxxxxxxxxxx',
|
32
|
+
}
|
33
|
+
|
34
|
+
Bot.new(settings).listen.always
|
35
|
+
```
|
36
|
+
|
37
|
+
To enable XMPP/Jabber on your Hipchat and be able to get the jids you need, go to: https://hipchat.yourCompanyDomain.com/account/xmpp
|
38
|
+
|
39
|
+
The MASTER_ROOM will be the room where you will be able to create other bots and will have special treatment.
|
40
|
+
|
41
|
+
The MASTER_USERS will have full access to everything. The names should be written exactly the same like they appear on hipchat.
|
42
|
+
|
43
|
+
I recommend to create an specific user on hipchat to be the bot so less risks.
|
44
|
+
|
45
|
+
Add the jid for that user specifying the hipchat domain in your company and finishing with /bot
|
46
|
+
|
47
|
+
For the token remember you need to generate a token on the hipchat app for the bot user.
|
48
|
+
To generate the token go to: https://hipchat.yourCompanyDomain.com/account/api
|
49
|
+
|
50
|
+
## Usage
|
51
|
+
|
52
|
+
### creating the MASTER BOT
|
53
|
+
Let's guess the file you created was called my_smart_bot.rb so, just run it:
|
54
|
+
```
|
55
|
+
ruby my_smart_bot.rb
|
56
|
+
```
|
57
|
+
|
58
|
+
After the run, it will be generated a rules file with the same name but adding _rules, in this example: my_smart_bot_rules.rb
|
59
|
+
|
60
|
+
The rules file can be edited and will be only affecting this particular bot.
|
61
|
+
|
62
|
+
You can add all the rules you want for your bot in the rules file, this is an example:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
def rules(from, command, processed)
|
66
|
+
firstname = from.split(" ").first
|
67
|
+
case command
|
68
|
+
|
69
|
+
# help: echo SOMETHING
|
70
|
+
# help: repeats SOMETHING
|
71
|
+
# help:
|
72
|
+
when /echo\s(.+)/i
|
73
|
+
respond $1
|
74
|
+
|
75
|
+
# help: go to sleep
|
76
|
+
# help: it will sleep the bot for 10 seconds
|
77
|
+
# help:
|
78
|
+
when /go\sto\ssleep/i
|
79
|
+
unless @questions.keys.include?(from)
|
80
|
+
ask("do you want me to take a siesta?", command, from)
|
81
|
+
else
|
82
|
+
case @questions[from]
|
83
|
+
when /yes/i, /yep/i, /sure/i
|
84
|
+
respond "zZzzzzzZZZZZZzzzzzzz!"
|
85
|
+
respond "I'll be sleeping for 10 secs... just for you"
|
86
|
+
sleep 10
|
87
|
+
when /no/i, /nope/i, /cancel/i
|
88
|
+
@questions.delete(from)
|
89
|
+
respond "Thanks, I'm happy to be awake"
|
90
|
+
else
|
91
|
+
respond "I don't understand"
|
92
|
+
ask("are you sure do you want me to sleep? (yes or no)", "go to sleep", from)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
else
|
96
|
+
unless processed
|
97
|
+
resp = %w{ what huh sorry }.sample
|
98
|
+
respond "#{firstname}: #{resp}?"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
```
|
104
|
+
|
105
|
+
### Available commands even when the bot is not listening to you
|
106
|
+
Some of the commands are available always even when the bot is not listening to you but it is running
|
107
|
+
|
108
|
+
**_`bot help`_**
|
109
|
+
|
110
|
+
**_`bot what can I do?`_**
|
111
|
+
|
112
|
+
>It will display all the commands we can use
|
113
|
+
>What is displayed by this command is what is written on your rules file like this: #help: THE TEXT TO SHOW
|
114
|
+
|
115
|
+
**_`Hello Bot`_**
|
116
|
+
|
117
|
+
**_`Hello THE_FIRSTNAME_OF_THE_BOT`_**
|
118
|
+
|
119
|
+
>Also apart of Hello you can use Hallo, Hi, Hola, What's up, Hey, Zdravo, Molim, Hæ
|
120
|
+
|
121
|
+
>Bot starts listening to you
|
122
|
+
|
123
|
+
**_`Bye Bot`_**
|
124
|
+
|
125
|
+
**_`Bye THE_FIRST_NAME_OF_THE_BOT`_**
|
126
|
+
|
127
|
+
>Also apart of Bye you can use Bæ, Good Bye, Adiós, Ciao, Bless, Bless Bless, Zbogom, Adeu
|
128
|
+
|
129
|
+
>Bot stops listening to you
|
130
|
+
|
131
|
+
**_`exit bot`_**
|
132
|
+
|
133
|
+
**_`quit bot`_**
|
134
|
+
|
135
|
+
**_`close bot`_**
|
136
|
+
|
137
|
+
>The bot stops running and also stops all the bots created from this master room
|
138
|
+
|
139
|
+
>You can use this command only if you are an admin user and you are on the master room
|
140
|
+
|
141
|
+
**_`start bot`_**
|
142
|
+
|
143
|
+
**_`start this bot`_**
|
144
|
+
|
145
|
+
>The bot will start to listen
|
146
|
+
|
147
|
+
>You can use this command only if you are an admin user
|
148
|
+
|
149
|
+
**_`pause bot`_**
|
150
|
+
|
151
|
+
**_`pause this bot`_**
|
152
|
+
|
153
|
+
>The bot will pause so it will listen only to admin commands
|
154
|
+
|
155
|
+
>You can use this command only if you are an admin user
|
156
|
+
|
157
|
+
**_`bot status`_**
|
158
|
+
|
159
|
+
>Displays the status of the bot
|
160
|
+
|
161
|
+
>If on master room and admin user also it will display info about bots created
|
162
|
+
|
163
|
+
**_`create bot on ROOM_NAME`_**
|
164
|
+
|
165
|
+
>Creates a new bot on the room specified.
|
166
|
+
|
167
|
+
>hipchat_smart will create a default rules file specific for your room.
|
168
|
+
You can edit it and add the rules you want.
|
169
|
+
As soon as you save the file after editing it will become available on your room.
|
170
|
+
|
171
|
+
>It will work only if you are on Master room
|
172
|
+
|
173
|
+
**_`kill bot on ROOM_NAME`_**
|
174
|
+
|
175
|
+
>Kills the bot on the specified room
|
176
|
+
|
177
|
+
>Only works if you are on Master room and you created that bot or you are an admin user
|
178
|
+
|
179
|
+
### Available commands only when listening to you or on demand
|
180
|
+
|
181
|
+
All the commands described on here or on your specific Rules file can be used when the bot is listening to you or on demand.
|
182
|
+
|
183
|
+
For the bot to start listening to you you need to use the "Hi bot" command or one of the aliases
|
184
|
+
|
185
|
+
Also you can call any of these commands on demand by using:
|
186
|
+
|
187
|
+
**_`!THE_COMMAND`_**
|
188
|
+
|
189
|
+
**_`@bot THE_COMMAND`_**
|
190
|
+
|
191
|
+
**_`@FIRST_NAME_BOT THE_COMMAND`_**
|
192
|
+
|
193
|
+
**_`FIRST_NAME_BOT THE_COMMAND`_**
|
194
|
+
|
195
|
+
Apart of the specific commands you define on the rules file of the room, you can use:
|
196
|
+
|
197
|
+
**_`ruby RUBY_CODE`_**
|
198
|
+
|
199
|
+
**_`/code RUBY_CODE`_**
|
200
|
+
|
201
|
+
>runs the code supplied and returns the output. Examples:
|
202
|
+
|
203
|
+
>ruby require 'json'; res=[]; 20.times {res<<rand(100)}; my_json={result: res}; puts my_json.to_json
|
204
|
+
|
205
|
+
>/code puts (34344/99)*(34+14)
|
206
|
+
|
207
|
+
|
208
|
+
**_`add shortcut NAME: COMMAND`_**
|
209
|
+
|
210
|
+
**_`add shortcut for all NAME: COMMAND`_**
|
211
|
+
|
212
|
+
**_`shortchut NAME: COMMAND`_**
|
213
|
+
|
214
|
+
**_`shortchut for all NAME: COMMAND`_**
|
215
|
+
|
216
|
+
>It will add a shortcut that will execute the command we supply.
|
217
|
+
|
218
|
+
>In case we supply 'for all' then the shorcut will be available for everybody
|
219
|
+
|
220
|
+
>Example:
|
221
|
+
>add shortcut for all Spanish account: /code require 'iso/iban'; 10.times {puts ISO::IBAN.random('ES')}
|
222
|
+
|
223
|
+
>Then to call this shortcut:
|
224
|
+
|
225
|
+
>/sc spanish account
|
226
|
+
|
227
|
+
>/shortcut Spanish Account
|
228
|
+
|
229
|
+
**_`delete shortcut NAME`_**
|
230
|
+
|
231
|
+
>It will delete the shortcut with the supplied name
|
232
|
+
|
233
|
+
**_`see shortcuts`_**
|
234
|
+
|
235
|
+
>It will display the shortcuts stored for the user and for :all
|
236
|
+
|
237
|
+
**_`jid room ROOM_NAME`_**
|
238
|
+
>shows the jid of a room name
|
239
|
+
|
240
|
+
|
241
|
+
## Contributing
|
242
|
+
|
243
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/marioruiz/hipchat_smart.
|
244
|
+
|
245
|
+
|
246
|
+
## License
|
247
|
+
|
248
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
249
|
+
|
@@ -0,0 +1,652 @@
|
|
1
|
+
require 'xmpp4r'
|
2
|
+
require 'xmpp4r/muc/helper/simplemucclient'
|
3
|
+
require 'xmpp4r/muc/helper/mucbrowser'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'cgi'
|
6
|
+
require 'json'
|
7
|
+
require 'hipchat'
|
8
|
+
require 'logger'
|
9
|
+
|
10
|
+
if ARGV.size==0
|
11
|
+
ROOM = MASTER_ROOM
|
12
|
+
ON_MASTER_ROOM = true
|
13
|
+
ADMIN_USERS = MASTER_USERS
|
14
|
+
RULES_FILE = "#{$0.gsub('.rb', '_rules.rb')}" unless defined?(RULES_FILE)
|
15
|
+
STATUS_INIT = :on
|
16
|
+
else
|
17
|
+
ON_MASTER_ROOM = false
|
18
|
+
ROOM = ARGV[0]
|
19
|
+
ADMIN_USERS=ARGV[1].split(",")
|
20
|
+
RULES_FILE=ARGV[2]
|
21
|
+
STATUS_INIT = ARGV[3].to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
SHORTCUTS_FILE = "hipchat_smart_shortcuts_#{ROOM}.rb".gsub(" ", "_")
|
25
|
+
|
26
|
+
class Bot
|
27
|
+
|
28
|
+
attr_accessor :config, :client, :muc, :muc_browser
|
29
|
+
|
30
|
+
def initialize(config)
|
31
|
+
Dir.mkdir("./logs") unless Dir.exist?("./logs")
|
32
|
+
Dir.mkdir("./shortcuts") unless Dir.exist?("./shortcuts")
|
33
|
+
logfile=File.basename(RULES_FILE.gsub("_rules_", "_logs_"), ".rb")+".log"
|
34
|
+
@logger = Logger.new("./logs/#{logfile}")
|
35
|
+
config_log=config.dup
|
36
|
+
config_log.delete(:password)
|
37
|
+
@logger.info "Initializing bot: #{config_log.inspect}"
|
38
|
+
|
39
|
+
#XMPP namespace for Hipchat Server by default, if not supplied with room
|
40
|
+
config[:room] = ROOM
|
41
|
+
if config[:room].include?("@")
|
42
|
+
@xmpp_namespace = config[:room].scan(/.+@(.+)/).join
|
43
|
+
else
|
44
|
+
@xmpp_namespace = "conf.btf.hipchat.com"
|
45
|
+
end
|
46
|
+
|
47
|
+
config[:room]=config[:room]+"@"+@xmpp_namespace
|
48
|
+
|
49
|
+
self.config = config
|
50
|
+
self.client = Jabber::Client.new(config[:jid])
|
51
|
+
self.muc = Jabber::MUC::SimpleMUCClient.new(client)
|
52
|
+
self.muc_browser = Jabber::MUC::MUCBrowser.new(client)
|
53
|
+
|
54
|
+
if Jabber.logger = config[:debug]
|
55
|
+
Jabber.debug = true
|
56
|
+
end
|
57
|
+
|
58
|
+
@listening = Array.new
|
59
|
+
|
60
|
+
@bots_created=Hash.new()
|
61
|
+
@shortcuts=Hash.new()
|
62
|
+
@shortcuts[:all]=Hash.new()
|
63
|
+
|
64
|
+
if File.exist?("./shortcuts/#{SHORTCUTS_FILE}")
|
65
|
+
file_sc = IO.readlines("./shortcuts/#{SHORTCUTS_FILE}").join
|
66
|
+
unless file_sc.to_s() == ""
|
67
|
+
@shortcuts = eval(file_sc)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if ON_MASTER_ROOM and File.exist?($0.gsub(".rb", "_bots.rb"))
|
72
|
+
file_conf = IO.readlines($0.gsub(".rb", "_bots.rb")).join
|
73
|
+
unless file_conf.to_s() == ""
|
74
|
+
@bots_created = eval(file_conf)
|
75
|
+
if @bots_created.kind_of?(Hash)
|
76
|
+
@bots_created.each {|key, value|
|
77
|
+
@logger.info "ruby #{$0} \"#{value[:jid].gsub(/@.+/, '')}\" \"#{value[:admins]}\" \"#{value[:rules_file]}\" #{value[:status]}"
|
78
|
+
t = Thread.new do
|
79
|
+
`ruby #{$0} \"#{value[:jid].gsub(/@.+/, '')}\" \"#{value[:admins]}\" \"#{value[:rules_file]}\" #{value[:status]}`
|
80
|
+
end
|
81
|
+
value[:thread]=t
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
client.connect
|
88
|
+
client.auth(config[:password])
|
89
|
+
client.on_exception do |exc, jab, where|
|
90
|
+
@logger.fatal "CLIENT EXCEPTION on #{where}: #{exc}"
|
91
|
+
sleep 10
|
92
|
+
#todo: reconnect
|
93
|
+
end
|
94
|
+
config.delete(:password)
|
95
|
+
client.send(Jabber::Presence.new.set_type(:available))
|
96
|
+
@status = STATUS_INIT
|
97
|
+
@questions = Hash.new()
|
98
|
+
@rooms_jid=Hash.new()
|
99
|
+
@rooms_name=Hash.new()
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def update_bots_file
|
104
|
+
file = File.open($0.gsub(".rb", "_bots.rb"), 'w')
|
105
|
+
bots_created=@bots_created.dup
|
106
|
+
bots_created.each {|k, v| v[:thread]=""}
|
107
|
+
file.write bots_created.inspect
|
108
|
+
file.close
|
109
|
+
end
|
110
|
+
|
111
|
+
def update_shortcuts_file
|
112
|
+
file = File.open("./shortcuts/#{SHORTCUTS_FILE}", 'w')
|
113
|
+
file.write @shortcuts.inspect
|
114
|
+
file.close
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_rooms_name_and_jid
|
118
|
+
@rooms_jid=Hash.new()
|
119
|
+
@rooms_name=Hash.new()
|
120
|
+
muc_browser.muc_rooms(@xmpp_namespace).each {|jid, name|
|
121
|
+
jid=jid.to_s.gsub("@#{@xmpp_namespace}", "")
|
122
|
+
@rooms_jid[name]=jid
|
123
|
+
@rooms_name[jid]=name
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def listen
|
128
|
+
@salutations = [config[:nick].split(/\s+/).first, "bot"]
|
129
|
+
|
130
|
+
muc.on_message do |time, nick, text|
|
131
|
+
if nick==config[:nick] or nick==(config[:nick] + " · Bot") #if message is coming from the bot
|
132
|
+
begin
|
133
|
+
@logger.info "#{nick}: #{text}"
|
134
|
+
case text
|
135
|
+
when /^Bot has been killed by/
|
136
|
+
exit!
|
137
|
+
when /^Changed status on (.+) to :(.+)/i
|
138
|
+
room=$1
|
139
|
+
status=$2
|
140
|
+
@bots_created[room][:status]=status.to_sym
|
141
|
+
update_bots_file()
|
142
|
+
end
|
143
|
+
next #don't continue analyzing
|
144
|
+
rescue Exception => stack
|
145
|
+
@logger.fatal stack
|
146
|
+
next
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
if text.match?(/^\/(shortcut|sc)\s(.+)/i)
|
152
|
+
shortcut=text.scan(/\/\w+\s*(.+)\s*/i).join.downcase
|
153
|
+
if @shortcuts.keys.include?(nick) and @shortcuts[nick].keys.include?(shortcut)
|
154
|
+
text=@shortcuts[nick][shortcut]
|
155
|
+
elsif @shortcuts.keys.include?(:all) and @shortcuts[:all].keys.include?(shortcut)
|
156
|
+
text=@shortcuts[:all][shortcut]
|
157
|
+
else
|
158
|
+
respond "Shortcut not found"
|
159
|
+
next
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
if @questions.keys.include?(nick)
|
165
|
+
command=@questions[nick]
|
166
|
+
@questions[nick]=text
|
167
|
+
else
|
168
|
+
command=text
|
169
|
+
end
|
170
|
+
|
171
|
+
begin
|
172
|
+
t = Thread.new do
|
173
|
+
begin
|
174
|
+
processed = process(nick, command)
|
175
|
+
@logger.info "command: #{nick}> #{command}" if processed
|
176
|
+
if @status==:on and
|
177
|
+
((@questions.keys.include?(nick) or
|
178
|
+
@listening.include?(nick) or
|
179
|
+
command.match?(/^@?#{@salutations.join("|")}:*\s+(.+)$/i) or
|
180
|
+
command.match?(/^!(.+)$/)))
|
181
|
+
@logger.info "command: #{nick}> #{command}" unless processed
|
182
|
+
begin
|
183
|
+
eval(File.new(RULES_FILE).read) if File.exist?(RULES_FILE)
|
184
|
+
rescue Exception => stack
|
185
|
+
@logger.fatal "ERROR ON RULES FILE: #{RULES_FILE}"
|
186
|
+
@logger.fatal stack
|
187
|
+
end
|
188
|
+
if defined?(rules)
|
189
|
+
command[0]="" if command[0]=="!"
|
190
|
+
command.gsub!(/^@\w+:*\s*/, "")
|
191
|
+
rules(nick, command, processed)
|
192
|
+
else
|
193
|
+
@logger.warn "It seems like rules method is not defined"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
rescue Exception => stack
|
197
|
+
@logger.fatal stack
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
rescue => e
|
203
|
+
@logger.error "exception: #{e.inspect}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
muc.join(config[:room] + '/' + config[:nick])
|
208
|
+
respond "Bot started"
|
209
|
+
@logger.info "Bot listening"
|
210
|
+
self
|
211
|
+
end
|
212
|
+
|
213
|
+
#help: Commands you can use:
|
214
|
+
#help:
|
215
|
+
def process(from, command)
|
216
|
+
firstname = from.split(/ /).first
|
217
|
+
processed=true
|
218
|
+
|
219
|
+
case command
|
220
|
+
|
221
|
+
#help: Hello Bot
|
222
|
+
#help: Hello THE_FIRSTNAME_OF_THE_BOT.
|
223
|
+
#help: Also apart of Hello you can use Hallo, Hi, Hola, What's up, Hey, Zdravo, Molim, Hæ
|
224
|
+
#help: Bot starts listening to you
|
225
|
+
#help:
|
226
|
+
when /^(Hello|Hallo|Hi|Hola|What's\sup|Hey|Zdravo|Molim|Hæ)\s(#{@salutations.join("|")})\s*$/i
|
227
|
+
if @status==:on
|
228
|
+
greetings=['Hello', 'Hallo', 'Hi', 'Hola', "What's up", "Hey", "Zdravo", "Molim", "Hæ"].sample
|
229
|
+
respond "#{greetings} #{firstname}"
|
230
|
+
@listening<<from unless @listening.include?(from)
|
231
|
+
end
|
232
|
+
|
233
|
+
#help: Bye Bot
|
234
|
+
#help: Bye THE_FIRST_NAME_OF_THE_BOT
|
235
|
+
#help: Also apart of Bye you can use Bæ, Good Bye, Adiós, Ciao, Bless, Bless Bless, Zbogom, Adeu
|
236
|
+
#help: Bot stops listening to you
|
237
|
+
#help:
|
238
|
+
when /^(Bye|Bæ|Good\sBye|Adiós|Ciao|Bless|Bless\sBless|Zbogom|Adeu)\s(#{@salutations.join("|")})\s*$/i
|
239
|
+
if @status==:on
|
240
|
+
bye=['Bye', 'Bæ', 'Good Bye', 'Adiós', "Ciao", "Bless", "Bless bless", "Zbogom", "Adeu"].sample
|
241
|
+
respond "#{bye} #{firstname}"
|
242
|
+
@listening.delete(from)
|
243
|
+
end
|
244
|
+
|
245
|
+
#help: exit bot
|
246
|
+
#help: quit bot
|
247
|
+
#help: close bot
|
248
|
+
#help: The bot stops running and also stops all the bots created from this master room
|
249
|
+
#help: You can use this command only if you are an admin user and you are on the master room
|
250
|
+
#help:
|
251
|
+
when /^exit\sbot/i, /^quit\sbot/i, /^close\sbot/i
|
252
|
+
if ON_MASTER_ROOM
|
253
|
+
if ADMIN_USERS.include?(from) #admin user
|
254
|
+
unless @questions.keys.include?(from)
|
255
|
+
ask("are you sure?", command, from)
|
256
|
+
else
|
257
|
+
case @questions[from]
|
258
|
+
when /yes/i, /yep/i, /sure/i
|
259
|
+
respond "Game over!"
|
260
|
+
respond "Ciao #{firstname}!"
|
261
|
+
@bots_created.each {|key, value|
|
262
|
+
value[:thread]=""
|
263
|
+
send_msg(key, "Bot has been killed by #{from}")
|
264
|
+
sleep 0.5
|
265
|
+
}
|
266
|
+
update_bots_file()
|
267
|
+
sleep 0.5
|
268
|
+
exit!
|
269
|
+
when /no/i, /nope/i, /cancel/i
|
270
|
+
@questions.delete(from)
|
271
|
+
respond "Thanks, I'm happy to be alive"
|
272
|
+
else
|
273
|
+
respond "I don't understand"
|
274
|
+
ask("are you sure do you want me to close? (yes or no)", "quit bot", from)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
else
|
278
|
+
respond "Only admin users can kill me"
|
279
|
+
end
|
280
|
+
|
281
|
+
else
|
282
|
+
respond "To do this you need to be an admin user in the master room"
|
283
|
+
end
|
284
|
+
|
285
|
+
#help: start bot
|
286
|
+
#help: start this bot
|
287
|
+
#help: the bot will start to listen
|
288
|
+
#help: You can use this command only if you are an admin user
|
289
|
+
#help:
|
290
|
+
when /^start\s(this\s)?bot$/i
|
291
|
+
if ADMIN_USERS.include?(from) #admin user
|
292
|
+
respond "This bot is running and listening from now on. You can pause again: pause this bot"
|
293
|
+
@status=:on
|
294
|
+
unless ON_MASTER_ROOM
|
295
|
+
get_rooms_name_and_jid() unless @rooms_name.keys.include?(MASTER_ROOM) and @rooms_name.keys.include?(ROOM)
|
296
|
+
send_msg @rooms_name[MASTER_ROOM], "Changed status on #{@rooms_name[ROOM]} to :on"
|
297
|
+
end
|
298
|
+
else
|
299
|
+
respond "Only admin users can change my status"
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
#help: pause bot
|
304
|
+
#help: pause this bot
|
305
|
+
#help: the bot will pause so it will listen only to admin commands
|
306
|
+
#help: You can use this command only if you are an admin user
|
307
|
+
#help:
|
308
|
+
when /^pause\s(this\s)?bot$/i
|
309
|
+
if ADMIN_USERS.include?(from) #admin user
|
310
|
+
respond "This bot is paused from now on. You can start it again: start this bot"
|
311
|
+
respond "zZzzzzZzzzzZZZZZZzzzzzzzz"
|
312
|
+
@status=:paused
|
313
|
+
unless ON_MASTER_ROOM
|
314
|
+
get_rooms_name_and_jid() unless @rooms_name.keys.include?(MASTER_ROOM) and @rooms_name.keys.include?(ROOM)
|
315
|
+
send_msg @rooms_name[MASTER_ROOM], "Changed status on #{@rooms_name[ROOM]} to :paused"
|
316
|
+
end
|
317
|
+
else
|
318
|
+
respond "Only admin users can put me on pause"
|
319
|
+
end
|
320
|
+
|
321
|
+
|
322
|
+
#help: bot status
|
323
|
+
#help: Displays the status of the bot
|
324
|
+
#help: If on master room and admin user also it will display info about bots created
|
325
|
+
#help:
|
326
|
+
when /^bot\sstatus/i
|
327
|
+
respond "Status: #{@status}. Rules file: #{File.basename RULES_FILE} "
|
328
|
+
if @status==:on
|
329
|
+
respond "I'm listening to [#{@listening.join(", ")}]"
|
330
|
+
if ON_MASTER_ROOM and ADMIN_USERS.include?(from)
|
331
|
+
@bots_created.each {|key, value|
|
332
|
+
respond "#{key}: #{value}"
|
333
|
+
}
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
#help: create bot on ROOM_NAME
|
338
|
+
#help: creates a new bot on the room specified
|
339
|
+
#help: it will work only if you are on Master room
|
340
|
+
#help:
|
341
|
+
when /^create\sbot\son\s(.+)\s*/i
|
342
|
+
if ON_MASTER_ROOM
|
343
|
+
room=$1
|
344
|
+
if @bots_created.keys.include?(room)
|
345
|
+
respond "There is already a bot in this room: #{room}, kill it before"
|
346
|
+
else
|
347
|
+
rooms=Hash.new()
|
348
|
+
muc_browser.muc_rooms(@xmpp_namespace).each {|jid, name|
|
349
|
+
rooms[name]=jid
|
350
|
+
}
|
351
|
+
if rooms.keys.include?(room)
|
352
|
+
jid=rooms[room]
|
353
|
+
if jid!=config[:room]
|
354
|
+
jid=jid.to_s.gsub(/@.+/, '')
|
355
|
+
begin
|
356
|
+
rules_file="hipchat_smart_rules_#{jid}_#{from.gsub(" ", "_")}.rb"
|
357
|
+
if defined?(RULES_FOLDER)
|
358
|
+
rules_file=RULES_FOLDER+rules_file
|
359
|
+
else
|
360
|
+
Dir.mkdir("rules") unless Dir.exist?("rules")
|
361
|
+
Dir.mkdir("rules/#{jid}") unless Dir.exist?("rules/#{jid}")
|
362
|
+
rules_file="./rules/#{jid}/" + rules_file
|
363
|
+
end
|
364
|
+
require 'fileutils'
|
365
|
+
default_rules=(__FILE__).gsub(".rb", "_rules.rb")
|
366
|
+
File.delete(rules_file) if File.exist?(rules_file)
|
367
|
+
FileUtils.copy_file(default_rules, rules_file) unless File.exist?(rules_file)
|
368
|
+
admin_users=Array.new()
|
369
|
+
admin_users=[from]+MASTER_USERS
|
370
|
+
admin_users.uniq!
|
371
|
+
@logger.info "ruby #{$0} \"#{jid}\" \"#{admin_users.join(",")}\" \"#{rules_file}\" :on"
|
372
|
+
t = Thread.new do
|
373
|
+
`ruby #{$0} \"#{jid}\" \"#{admin_users.join(",")}\" \"#{rules_file}\" :on`
|
374
|
+
end
|
375
|
+
@bots_created[room]={
|
376
|
+
creator_name: from,
|
377
|
+
jid: jid,
|
378
|
+
status: :on,
|
379
|
+
created: Time.now.strftime('%Y-%m-%dT%H:%M:%S.000Z')[0..18],
|
380
|
+
rules_file: rules_file,
|
381
|
+
admins: admin_users.join(","),
|
382
|
+
thread: t
|
383
|
+
}
|
384
|
+
respond "The bot has been created on room: #{room}. Rules file: #{File.basename rules_file}"
|
385
|
+
update_bots_file()
|
386
|
+
rescue Exception => stack
|
387
|
+
@logger.fatal stack
|
388
|
+
message="Problem creating the bot on room #{room}. Error: <#{stack}>."
|
389
|
+
@logger.error message
|
390
|
+
respond message
|
391
|
+
end
|
392
|
+
else
|
393
|
+
respond "There is already a bot in this room: #{room}, and it is the Master Room!"
|
394
|
+
end
|
395
|
+
|
396
|
+
else
|
397
|
+
respond "There is no room with that name: #{room}, please be sure is written exactly the same"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
else
|
401
|
+
respond "Sorry I cannot create bots from this room, please visit the master room"
|
402
|
+
end
|
403
|
+
|
404
|
+
#help: kill bot on ROOM_NAME
|
405
|
+
#help: kills the bot on the specified room
|
406
|
+
#help: Only works if you are on Master room and you created that bot or you are an admin user
|
407
|
+
#help:
|
408
|
+
when /^kill\sbot\son\s(.+)\s*/i
|
409
|
+
if ON_MASTER_ROOM
|
410
|
+
room=$1
|
411
|
+
if @bots_created.keys.include?(room)
|
412
|
+
if @bots_created[room][:admins].split(",").include?(from)
|
413
|
+
if @bots_created[room][:thread].kind_of?(Thread) and @bots_created[room][:thread].alive?
|
414
|
+
@bots_created[room][:thread].kill
|
415
|
+
end
|
416
|
+
@bots_created.delete(room)
|
417
|
+
update_bots_file()
|
418
|
+
respond "Bot on room: #{room}, has been killed and deleted."
|
419
|
+
send_msg(room, "Bot has been killed by #{from}")
|
420
|
+
else
|
421
|
+
respond "You need to be the creator or an admin of that room"
|
422
|
+
end
|
423
|
+
else
|
424
|
+
respond "There is no bot in this room: #{room}"
|
425
|
+
end
|
426
|
+
else
|
427
|
+
respond "Sorry I cannot kill bots from this room, please visit the master room"
|
428
|
+
end
|
429
|
+
|
430
|
+
#help: bot help
|
431
|
+
#help: bot what can I do?
|
432
|
+
#help: it will display this help
|
433
|
+
#help:
|
434
|
+
when /^bot help/i, /^bot,? what can I do/i
|
435
|
+
help_message = IO.readlines(__FILE__).join
|
436
|
+
help_message_rules = IO.readlines(RULES_FILE).join
|
437
|
+
respond "/quote " + help_message.scan(/#\s*help\s*:(.*)/).join("\n")
|
438
|
+
respond "/quote " + help_message_rules.scan(/#\s*help\s*:(.*)/).join("\n")
|
439
|
+
|
440
|
+
else
|
441
|
+
processed = false
|
442
|
+
end
|
443
|
+
|
444
|
+
#only when :on and (listening or on demand)
|
445
|
+
if @status==:on and
|
446
|
+
((@questions.keys.include?(from) or
|
447
|
+
@listening.include?(from) or
|
448
|
+
command.match?(/^@?#{@salutations.join("|")}:*\s+(.+)$/i) or
|
449
|
+
command.match?(/^!(.+)$/)))
|
450
|
+
processed2=true
|
451
|
+
|
452
|
+
# help:
|
453
|
+
# help: These commands will run only when bot is listening to you or on demand, for example:
|
454
|
+
# help: !THE_COMMAND
|
455
|
+
# help: @bot THE_COMMAND
|
456
|
+
# help: @FIRST_NAME_BOT THE_COMMAND
|
457
|
+
# help: FIRST_NAME_BOT THE_COMMAND.
|
458
|
+
# help:
|
459
|
+
case command
|
460
|
+
|
461
|
+
#help: add shortcut NAME: COMMAND
|
462
|
+
#help: add shortcut for all NAME: COMMAND
|
463
|
+
#help: shortchut NAME: COMMAND
|
464
|
+
#help: shortchut for all NAME: COMMAND
|
465
|
+
#help: It will add a shortcut that will execute the command we supply.
|
466
|
+
#help: In case we supply 'for all' then the shorcut will be available for everybody
|
467
|
+
#help: Example:
|
468
|
+
#help: add shortcut for all Spanish account: /code require 'iso/iban'; 10.times {puts ISO::IBAN.random('ES')}
|
469
|
+
#help: Then to call this shortcut:
|
470
|
+
#help: /sc spanish account
|
471
|
+
#help: /shortcut Spanish Account
|
472
|
+
#help:
|
473
|
+
when /(add\s)?shortcut\s(for\sall)?\s*(.+):\s(.+)/i
|
474
|
+
for_all=$2
|
475
|
+
shortcut_name=$3.to_s.downcase
|
476
|
+
command_to_run=$4
|
477
|
+
@shortcuts[from]=Hash.new() unless @shortcuts.keys.include?(from)
|
478
|
+
|
479
|
+
if !ADMIN_USERS.include?(from) and @shortcuts[:all].include?(shortcut_name) and !@shortcuts[from].include?(shortcut_name)
|
480
|
+
respond "Only the creator of the shortcut or an admin user can modify it"
|
481
|
+
elsif !@shortcuts[from].include?(shortcut_name)
|
482
|
+
#new shortcut
|
483
|
+
@shortcuts[from][shortcut_name]=command_to_run
|
484
|
+
@shortcuts[:all][shortcut_name]=command_to_run if for_all.to_s!=""
|
485
|
+
update_shortcuts_file()
|
486
|
+
respond "shortcut added"
|
487
|
+
else
|
488
|
+
|
489
|
+
#are you sure? to avoid overwriting existing
|
490
|
+
unless @questions.keys.include?(from)
|
491
|
+
ask("The shortcut already exists, are you sure you want to overwrite it?", command, from)
|
492
|
+
else
|
493
|
+
case @questions[from]
|
494
|
+
when /^(yes|yep)/i
|
495
|
+
@shortcuts[from][shortcut_name]=command_to_run
|
496
|
+
@shortcuts[:all][shortcut_name]=command_to_run if for_all.to_s!=""
|
497
|
+
update_shortcuts_file()
|
498
|
+
respond "shortcut added"
|
499
|
+
@questions.delete(from)
|
500
|
+
when /^no/i
|
501
|
+
respond "ok, I won't add it"
|
502
|
+
@questions.delete(from)
|
503
|
+
else
|
504
|
+
respond "I don't understand, yes or no?"
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
end
|
509
|
+
|
510
|
+
#help: delete shortcut NAME
|
511
|
+
#help: It will delete the shortcut with the supplied name
|
512
|
+
#help:
|
513
|
+
when /delete\sshortcut\s(.+)/i
|
514
|
+
shortcut=$1.to_s.downcase
|
515
|
+
deleted=false
|
516
|
+
|
517
|
+
if !ADMIN_USERS.include?(from) and @shortcuts[:all].include?(shortcut) and !@shortcuts[from].include?(shortcut)
|
518
|
+
respond "Only the creator of the shortcut or an admin user can delete it"
|
519
|
+
elsif (@shortcuts.keys.include?(from) and @shortcuts[from].keys.include?(shortcut)) or
|
520
|
+
(ADMIN_USERS.include?(from) and @shortcuts[:all].include?(shortcut))
|
521
|
+
#are you sure? to avoid deleting by mistake
|
522
|
+
unless @questions.keys.include?(from)
|
523
|
+
ask("are you sure you want to delete it?", command, from)
|
524
|
+
else
|
525
|
+
case @questions[from]
|
526
|
+
when /^(yes|yep)/i
|
527
|
+
respond "shortcut deleted!"
|
528
|
+
respond "#{shortcut}: #{@shortcuts[from][shortcut]}"
|
529
|
+
@shortcuts[from].delete(shortcut)
|
530
|
+
@shortcuts[:all].delete(shortcut)
|
531
|
+
@questions.delete(from)
|
532
|
+
update_shortcuts_file()
|
533
|
+
when /^no/i
|
534
|
+
respond "ok, I won't delete it"
|
535
|
+
@questions.delete(from)
|
536
|
+
else
|
537
|
+
respond "I don't understand, yes or no?"
|
538
|
+
end
|
539
|
+
end
|
540
|
+
else
|
541
|
+
respond "shortcut not found"
|
542
|
+
end
|
543
|
+
|
544
|
+
#help: see shortcuts
|
545
|
+
#help: It will display the shortcuts stored for the user and for :all
|
546
|
+
#help:
|
547
|
+
when /see\sshortcuts/i
|
548
|
+
msg=""
|
549
|
+
if @shortcuts[:all].keys.size>0
|
550
|
+
msg="Available shortcuts for all:\n"
|
551
|
+
@shortcuts[:all].each {|name, value|
|
552
|
+
msg+="#{name}: #{value}\n"
|
553
|
+
}
|
554
|
+
respond msg
|
555
|
+
end
|
556
|
+
|
557
|
+
if @shortcuts.keys.include?(from) and @shortcuts[from].keys.size>0
|
558
|
+
new_hash=@shortcuts[from].dup
|
559
|
+
@shortcuts[:all].keys.each {|k| new_hash.delete(k)}
|
560
|
+
if new_hash.keys.size>0
|
561
|
+
msg="Available shortcuts for #{from}:\n"
|
562
|
+
new_hash.each {|name, value|
|
563
|
+
msg+="#{name}: #{value}\n"
|
564
|
+
}
|
565
|
+
respond msg
|
566
|
+
end
|
567
|
+
end
|
568
|
+
respond "No shortcuts found" if msg==""
|
569
|
+
|
570
|
+
#help: jid room ROOM_NAME
|
571
|
+
#help: shows the jid of a room name
|
572
|
+
#help:
|
573
|
+
when /jid room (.+)/
|
574
|
+
room_name=$1
|
575
|
+
get_rooms_name_and_jid()
|
576
|
+
if @rooms_jid.keys.include?(room_name)
|
577
|
+
respond "the jid of #{room_name} is #{@rooms_jid[room_name]}"
|
578
|
+
else
|
579
|
+
respond "room: #{room_name} not found"
|
580
|
+
end
|
581
|
+
|
582
|
+
# help: ruby RUBY_CODE
|
583
|
+
# help: /code RUBY_CODE
|
584
|
+
# help: runs the code supplied and returns the output. Examples:
|
585
|
+
# help: ruby require 'json'; res=[]; 20.times {res<<rand(100)}; my_json={result: res}; puts my_json.to_json
|
586
|
+
# help: /code puts (34344/99)*(34+14)
|
587
|
+
# help:
|
588
|
+
when /ruby\s(.+)/im, /\/code\s(.+)/im
|
589
|
+
code=$1
|
590
|
+
code.gsub!("\\n", "\n")
|
591
|
+
unless code.match?(/System/i) or code.match?(/Kernel/i) or code.include?("File") or
|
592
|
+
code.include?("`") or code.include?("exec") or code.include?("spawn") or code.include?("IO") or
|
593
|
+
code.match?(/open3/i) or code.match?(/bundle/i) or code.match?(/gemfile/i) or code.include?("%x") or
|
594
|
+
code.include?("ENV")
|
595
|
+
begin
|
596
|
+
require 'open3'
|
597
|
+
stdout, stderr, status = Open3.capture3("ruby -e \"#{code.gsub('"', '\"')}\"")
|
598
|
+
if stderr==""
|
599
|
+
if stdout==""
|
600
|
+
respond "Nothing returned. Remember you need to use p or puts to print"
|
601
|
+
else
|
602
|
+
respond stdout
|
603
|
+
end
|
604
|
+
else
|
605
|
+
respond stderr
|
606
|
+
end
|
607
|
+
rescue Exception => exc
|
608
|
+
respond exc
|
609
|
+
end
|
610
|
+
else
|
611
|
+
respond "Sorry I cannot run this due security issues"
|
612
|
+
end
|
613
|
+
|
614
|
+
else
|
615
|
+
processed2=false
|
616
|
+
end
|
617
|
+
processed=true if processed or processed2
|
618
|
+
end
|
619
|
+
|
620
|
+
return processed
|
621
|
+
end
|
622
|
+
|
623
|
+
def respond(msg)
|
624
|
+
muc.send Jabber::Message.new(muc.room, msg)
|
625
|
+
end
|
626
|
+
|
627
|
+
#context: previous message
|
628
|
+
#to: user that should answer
|
629
|
+
def ask(question, context, to)
|
630
|
+
muc.send Jabber::Message.new(muc.room, "#{to}: #{question}")
|
631
|
+
@questions[to]=context
|
632
|
+
end
|
633
|
+
|
634
|
+
# Uses the hipchat gem (REST)
|
635
|
+
# to: (String) Room name
|
636
|
+
# msg: (String) message to send
|
637
|
+
def send_msg(to, msg)
|
638
|
+
unless msg==""
|
639
|
+
hc_client=HipChat::Client.new(config[:token], :server_url => config[:jid].to_s.scan(/.+@(.+)\/.+/).join)
|
640
|
+
hc_client[to].send("Bot", msg)
|
641
|
+
end
|
642
|
+
|
643
|
+
end
|
644
|
+
|
645
|
+
|
646
|
+
def always
|
647
|
+
loop {sleep 1}
|
648
|
+
end
|
649
|
+
|
650
|
+
private :update_bots_file, :get_rooms_name_and_jid, :update_shortcuts_file
|
651
|
+
end
|
652
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#for the case of testing, just run this file adding in the end a call to rules with the parameters you want
|
2
|
+
if defined?(respond)
|
3
|
+
@testing = false
|
4
|
+
else
|
5
|
+
@testing = true
|
6
|
+
@questions = Hash.new()
|
7
|
+
|
8
|
+
def respond(message)
|
9
|
+
puts message
|
10
|
+
end
|
11
|
+
|
12
|
+
#context: previous message
|
13
|
+
#to: user that should answer
|
14
|
+
def ask(question, context, to)
|
15
|
+
puts "Bot: #{question}"
|
16
|
+
@questions[to]=context
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# from: Full name of the person sending the message
|
21
|
+
# command: command to run
|
22
|
+
# processed: in case the command has been already processed on Bot class, by default false
|
23
|
+
# help: These are specific commands on this bot.
|
24
|
+
# help: They will be accessible only when the bot is listening to you just writing the command
|
25
|
+
# help: or the bot is not listening to you but requested on demand, for example:
|
26
|
+
# help: !THE_COMMAND
|
27
|
+
# help: @bot THE_COMMAND
|
28
|
+
# help: @FIRST_NAME_BOT THE_COMMAND
|
29
|
+
# help: FIRST_NAME_BOT THE_COMMAND
|
30
|
+
# help:
|
31
|
+
def rules(from, command, processed)
|
32
|
+
if @testing
|
33
|
+
puts "#{from}: #{command}"
|
34
|
+
if @questions.keys.include?(from)
|
35
|
+
context = @questions[from]
|
36
|
+
@questions[from] = command
|
37
|
+
command = context
|
38
|
+
end
|
39
|
+
end
|
40
|
+
firstname = from.split(" ").first
|
41
|
+
case command
|
42
|
+
|
43
|
+
# help: echo SOMETHING
|
44
|
+
# help: repeats SOMETHING
|
45
|
+
# help:
|
46
|
+
when /echo\s(.+)/i
|
47
|
+
respond $1
|
48
|
+
|
49
|
+
# help: go to sleep
|
50
|
+
# help: it will sleep the bot for 10 seconds
|
51
|
+
# help:
|
52
|
+
when /go\sto\ssleep/i
|
53
|
+
unless @questions.keys.include?(from)
|
54
|
+
ask("do you want me to take a siesta?", command, from)
|
55
|
+
else
|
56
|
+
case @questions[from]
|
57
|
+
when /yes/i, /yep/i, /sure/i
|
58
|
+
respond "zZzzzzzZZZZZZzzzzzzz!"
|
59
|
+
respond "I'll be sleeping for 10 secs... just for you"
|
60
|
+
sleep 10
|
61
|
+
when /no/i, /nope/i, /cancel/i
|
62
|
+
@questions.delete(from)
|
63
|
+
respond "Thanks, I'm happy to be awake"
|
64
|
+
else
|
65
|
+
respond "I don't understand"
|
66
|
+
ask("are you sure do you want me to sleep? (yes or no)", "go to sleep", from)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
unless processed
|
71
|
+
resp = %w{ what huh sorry }.sample
|
72
|
+
respond "#{firstname}: #{resp}?"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
#for the case of testing just running this file, write the dialogue in here:
|
79
|
+
if @testing
|
80
|
+
rules "Peter Johson", "go to sleep, you look tired", false
|
81
|
+
rules "Peter Johson", "yes", false
|
82
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hipchat_smart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mario Ruiz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: xmpp4r
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.5'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.5.6
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.5'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.5.6
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: hipchat
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.6'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.6.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.6'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.6.0
|
53
|
+
description: The main scope of this gem is to be used internally in your company so
|
54
|
+
teams can create team rooms with their own bot to help them on their daily work,
|
55
|
+
almost everything is suitable to be automated!! hipchat_smart can create bots on
|
56
|
+
demand, create shortcuts, run ruby code... just on a chat room, you can access it
|
57
|
+
just from your mobile phone if you want and run those tests you forgot to run, get
|
58
|
+
the results, restart a server... no limits.
|
59
|
+
email: marioruizs@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files:
|
63
|
+
- LICENSE
|
64
|
+
- README.md
|
65
|
+
files:
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- lib/hipchat_smart.rb
|
69
|
+
- lib/hipchat_smart_rules.rb
|
70
|
+
homepage: https://github.com/MarioRuiz/hipchat_smart
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.4'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.6.11
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Create a hipchat bot that is really smart and so easy to expand, create new
|
94
|
+
bots on demand, run ruby code on chat, create shortcuts...
|
95
|
+
test_files: []
|