jabbot 0.3.2 → 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/README.md +72 -70
- data/lib/jabbot.rb +1 -2
- data/lib/jabbot/bot.rb +72 -58
- data/lib/jabbot/config.rb +67 -95
- data/lib/jabbot/handlers.rb +6 -14
- data/lib/jabbot/version.rb +3 -0
- data/test/helper.rb +1 -31
- data/test/test_bot.rb +5 -33
- data/test/test_config.rb +6 -67
- data/test/test_macros.rb +2 -2
- metadata +73 -64
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 275301838af799f27e719e700580c9d4accd3b61
|
4
|
+
data.tar.gz: 537c0a93513ab40c135ec60e526b5983b36b56c8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 398e664b0beb9b285f7c3de5122449639b135913d98a43214240363757068d34a87537e88fe7cdef7efccf62ff6739c686f800a105bf84546a496c806999488f
|
7
|
+
data.tar.gz: 62509ecd7c7e52fce6bb59ed314d878f6f7f2ca908237f641e969ff426019476ba4f6d59614fc74ef32d86d74deaeb84ee7d308d9358ebcb5b1284f4730ba682
|
data/README.md
CHANGED
@@ -2,79 +2,79 @@
|
|
2
2
|
|
3
3
|
## Description
|
4
4
|
|
5
|
-
Jabbot is a Ruby micro-framework for creating Jabber/MUC bots,
|
6
|
-
heavily inspired by Sinatra and Twibot.
|
5
|
+
Jabbot is a Ruby micro-framework for creating Jabber/MUC bots, heavily inspired by Sinatra and Twibot.
|
7
6
|
|
8
|
-
I modified the code of Twibot to fit my needs.
|
9
|
-
The original Twibot code is located at:
|
10
|
-
http://github.com/cjohansen/twibot/tree/master
|
7
|
+
I modified the code of Twibot to fit my needs. The original Twibot code is located at: <http://github.com/cjohansen/twibot>
|
11
8
|
|
12
|
-
A big thank you to Christian Johansen, who wrote the code for Twibot.
|
13
|
-
Jabbot is heavily based on his code.
|
9
|
+
A big thank you to Christian Johansen, who wrote the code for Twibot. Jabbot is heavily based on his code.
|
14
10
|
|
15
11
|
If your curious if this code is stable enough:
|
16
|
-
I have a bot instance running on my server for
|
17
|
-
and it works great :)
|
12
|
+
I have a bot instance running on my server for years now and it works great :)
|
18
13
|
|
19
|
-
|
14
|
+
Just keep in mind that the code is not the most beautiful, maybe has bugs or rough edges. Feel free to improve it. I use it as is.
|
20
15
|
|
21
|
-
### Simple example
|
22
16
|
|
23
|
-
|
24
|
-
message do |message, params|
|
25
|
-
post message.text
|
26
|
-
end
|
17
|
+
## Usage
|
27
18
|
|
28
|
-
|
29
|
-
# query "message" => "user" is just some syntax sugar
|
30
|
-
# query "message", "user" will work, too
|
31
|
-
query :from => [:cjno, :irbno] do |message, params|
|
32
|
-
post "#{message.user} I agree" => message.user
|
33
|
-
end
|
19
|
+
### Simple example
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
~~~ruby
|
22
|
+
configure do |conf|
|
23
|
+
conf.login = "my_account"
|
24
|
+
conf.password = "my_account"
|
25
|
+
conf.nick = "mybot"
|
26
|
+
conf.channel = "mychannel"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Receive messages, and post them publicly
|
30
|
+
message do |message, params|
|
31
|
+
post message.text
|
32
|
+
end
|
33
|
+
|
34
|
+
# Respond to query if they come from the right crowd
|
35
|
+
# query "message" => "user" is just some syntax sugar
|
36
|
+
# query "message", "user" will work, too
|
37
|
+
query :from => [:cjno, :irbno] do |message, params|
|
38
|
+
post "#{message.user} I agree" => message.user
|
39
|
+
end
|
40
|
+
|
41
|
+
# Log every single line
|
42
|
+
# (you can use "message :all" too ;)
|
43
|
+
message do |message, params|
|
44
|
+
MyApp.log_message(message)
|
45
|
+
end
|
46
|
+
~~~
|
40
47
|
|
41
48
|
### Running the bot
|
42
49
|
|
43
50
|
To run the bot, simply do:
|
44
51
|
|
45
|
-
|
52
|
+
~~~
|
53
|
+
ruby bot.rb
|
54
|
+
~~~
|
46
55
|
|
47
56
|
Jabbot uses the [at\_exit hook](http://ruby-doc.org/core/classes/Kernel.html#M005932) to start.
|
48
57
|
|
49
58
|
### Configuration
|
50
59
|
|
51
|
-
|
52
|
-
|
53
|
-
Jabbot looks for a configuration file in ./config/bot.yml. It should contain
|
54
|
-
atleast:
|
60
|
+
You have to configure your bot via ruby:
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
62
|
+
~~~ruby
|
63
|
+
configure do |conf|
|
64
|
+
conf.login = "my_account"
|
65
|
+
conf.nick = "mybot"
|
66
|
+
end
|
67
|
+
~~~
|
61
68
|
|
62
|
-
|
69
|
+
If you don't specify login and/or password in any of these ways, Jabbot will fail. The nick is automatically set to "jabbot" unless something different is defined. If you want you can set the XMPP Resource:
|
63
70
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
71
|
+
~~~ruby
|
72
|
+
configure do |conf|
|
73
|
+
conf.resource ="mybot_resource"
|
74
|
+
end
|
75
|
+
~~~
|
68
76
|
|
69
|
-
|
70
|
-
Nick is automatically set to "jabbot" unless something different is defined
|
71
|
-
If you want you can set the XMPP Resource:
|
72
|
-
|
73
|
-
configure do |conf|
|
74
|
-
conf.resource ="mybot_resource"
|
75
|
-
end
|
76
|
-
|
77
|
-
Default is "jabbot".
|
77
|
+
Default resource is "jabbot".
|
78
78
|
|
79
79
|
### "Routes"
|
80
80
|
|
@@ -91,39 +91,45 @@ Every matching block will be called.
|
|
91
91
|
|
92
92
|
Jabbot also supports regular expressions as routes:
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
94
|
+
~~~ruby
|
95
|
+
message /^time ([^\s]*) ([^\s]*)/ do |message, params|
|
96
|
+
# params is an array of matches when using regexp routes
|
97
|
+
time = MyTimeService.lookup(params[0], params[1])
|
98
|
+
post "Time is #{time} in #{params[:city]}, #{params[:country]}"
|
99
|
+
end
|
100
|
+
~~~
|
99
101
|
|
100
102
|
If all you need is exact word matching you can say so:
|
101
103
|
|
102
|
-
|
103
|
-
|
104
|
-
|
104
|
+
~~~ruby
|
105
|
+
message :exact => "pattern" do |message, params|
|
106
|
+
...
|
107
|
+
end
|
108
|
+
~~~
|
105
109
|
|
106
110
|
Internally this pattern is translated to `/\Apattern\Z/`, so you can use regex literals.
|
107
111
|
|
108
112
|
## Requirements
|
109
113
|
|
110
|
-
xmpp4r. You'll need atleast 0.4.
|
111
|
-
|
112
|
-
|
113
|
-
gem install xmpp4r
|
114
|
+
* xmpp4r. You'll need atleast 0.4. You can get it via rubygems: `gem install xmpp4r`
|
115
|
+
* eventmachine. `gem install eventmachine`
|
114
116
|
|
115
|
-
or get it from: http://home.gna.org/xmpp4r/
|
116
117
|
|
117
118
|
## Installation
|
118
119
|
|
119
120
|
Jabbot is available via gem:
|
120
121
|
|
121
|
-
|
122
|
+
~~~
|
123
|
+
gem install jabbot
|
124
|
+
~~~
|
122
125
|
|
123
126
|
## Is it Ruby 1.9?
|
124
127
|
|
125
|
-
|
126
|
-
|
128
|
+
Absolutely! I run it on 1.9.3 without problems (thanks to the updated xmpp4r).
|
129
|
+
|
130
|
+
## Is it Ruby 2.x?
|
131
|
+
|
132
|
+
It should, test pass. I'm not sure if it will work as expected.
|
127
133
|
|
128
134
|
## Samples
|
129
135
|
|
@@ -146,10 +152,6 @@ If you'd like to hack on jabbot, start by forking my repo on GitHub:
|
|
146
152
|
|
147
153
|
http://github.com/badboy/jabbot
|
148
154
|
|
149
|
-
jabbot needs xmpp4r, so just install it:
|
150
|
-
|
151
|
-
gem install xmpp4r
|
152
|
-
|
153
155
|
Then:
|
154
156
|
|
155
157
|
1. Clone down your fork
|
data/lib/jabbot.rb
CHANGED
@@ -6,14 +6,13 @@ require 'xmpp4r/version/helper/simpleresponder'
|
|
6
6
|
require 'yaml'
|
7
7
|
require File.join(File.dirname(__FILE__), 'hash')
|
8
8
|
|
9
|
+
require 'jabbot/version.rb'
|
9
10
|
require 'jabbot/bot.rb'
|
10
11
|
require 'jabbot/config.rb'
|
11
12
|
require 'jabbot/handlers.rb'
|
12
13
|
require 'jabbot/macros.rb'
|
13
14
|
|
14
15
|
module Jabbot
|
15
|
-
VERSION = '0.3.2'
|
16
|
-
|
17
16
|
@@app_file = lambda do
|
18
17
|
ignore = [
|
19
18
|
/lib\/twibot.*\.rb/, # Library
|
data/lib/jabbot/bot.rb
CHANGED
@@ -5,6 +5,38 @@ require File.join(File.expand_path(File.dirname(__FILE__)), 'handlers')
|
|
5
5
|
require 'eventmachine'
|
6
6
|
|
7
7
|
module Jabbot
|
8
|
+
# A message consists of the username, the text, a time when it was received
|
9
|
+
# and the type of the message.
|
10
|
+
#
|
11
|
+
# The type could be one Symbol of:
|
12
|
+
#
|
13
|
+
# * :public
|
14
|
+
# * :private
|
15
|
+
# * :join
|
16
|
+
# * :leave
|
17
|
+
# * :subject
|
18
|
+
#
|
19
|
+
Message = Struct.new(:user, :text, :time, :type) do
|
20
|
+
# Public: Converts the message to printable text.
|
21
|
+
#
|
22
|
+
# Returns a String containing the user's name and the text.
|
23
|
+
def to_s
|
24
|
+
"#{user}: #{text}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Encode a message in JSON
|
28
|
+
#
|
29
|
+
# Returns the json-ified String of the Hash representation of this message.
|
30
|
+
def to_json(*a)
|
31
|
+
{
|
32
|
+
:user => user,
|
33
|
+
:text => text,
|
34
|
+
:time => time,
|
35
|
+
:type => type
|
36
|
+
}.to_json(*a)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
8
40
|
# The main Bot class.
|
9
41
|
#
|
10
42
|
# It handles the connection as well as the method dispatching.
|
@@ -13,29 +45,17 @@ module Jabbot
|
|
13
45
|
attr_reader :client
|
14
46
|
attr_reader :users
|
15
47
|
|
16
|
-
Message = Struct.new(:user, :text, :time, :type) do
|
17
|
-
def to_s
|
18
|
-
"#{user}: #{text}"
|
19
|
-
end
|
20
|
-
|
21
|
-
# Encode a message in JSON
|
22
|
-
# A message is just a hash of its values
|
23
|
-
def to_json(*a)
|
24
|
-
{
|
25
|
-
:user => user,
|
26
|
-
:text => text,
|
27
|
-
:time => time,
|
28
|
-
:type => type
|
29
|
-
}.to_json(*a)
|
30
|
-
end
|
31
|
-
end
|
32
48
|
|
33
49
|
# Public: Initialize a Bot instance.
|
34
50
|
#
|
35
|
-
# options - A Jabbot::Config options instance
|
36
|
-
|
37
|
-
|
38
|
-
@config = options
|
51
|
+
# options - A Jabbot::Config options instance or a Hash of key-value
|
52
|
+
# configuration options (default: {}).
|
53
|
+
def initialize(options={})
|
54
|
+
@config = if options.kind_of?(Jabbot::Config)
|
55
|
+
options
|
56
|
+
else
|
57
|
+
Jabbot::Config.new(options)
|
58
|
+
end
|
39
59
|
@log = nil
|
40
60
|
@abort = false
|
41
61
|
@users = []
|
@@ -64,21 +84,21 @@ module Jabbot
|
|
64
84
|
#
|
65
85
|
# Returns nothing.
|
66
86
|
def connect
|
67
|
-
@jid = Jabber::JID.new(login)
|
68
|
-
@mucjid = Jabber::JID.new("#{channel}@#{server}")
|
87
|
+
@jid = Jabber::JID.new(config.login)
|
88
|
+
@mucjid = Jabber::JID.new("#{config.channel}@#{config.server}")
|
69
89
|
|
70
90
|
if @jid.node.nil?
|
71
91
|
raise "Your Jabber ID must contain a user name and therefore contain one @ character."
|
72
92
|
elsif @jid.resource
|
73
|
-
raise "If you intend to set a custom resource,
|
93
|
+
raise "If you intend to set a custom resource, define so in the config."
|
74
94
|
elsif @mucjid.node.nil?
|
75
95
|
raise "Please set a room name, e.g. myroom@conference.jabber.org"
|
76
96
|
elsif @mucjid.resource
|
77
97
|
raise "The MUC room must not contain a resource. Remove the slash!"
|
78
98
|
else
|
79
|
-
@jid.resource = config
|
80
|
-
@mucjid.resource = config
|
81
|
-
@users << config
|
99
|
+
@jid.resource = config.resource
|
100
|
+
@mucjid.resource = config.nick
|
101
|
+
@users << config.nick
|
82
102
|
end
|
83
103
|
|
84
104
|
@client = Jabber::Client.new(@jid)
|
@@ -92,10 +112,10 @@ module Jabbot
|
|
92
112
|
end
|
93
113
|
begin
|
94
114
|
@client.connect
|
95
|
-
@client.auth(password)
|
115
|
+
@client.auth(config.password)
|
96
116
|
@muc = Jabber::MUC::SimpleMUCClient.new(@client)
|
97
117
|
muc_handlers.call(@muc)
|
98
|
-
@muc.join(@mucjid)
|
118
|
+
@muc.join(@mucjid, config.channel_password)
|
99
119
|
@connected = true
|
100
120
|
rescue => errmsg
|
101
121
|
@connected = false
|
@@ -112,7 +132,7 @@ module Jabbot
|
|
112
132
|
#
|
113
133
|
# Returns nothing.
|
114
134
|
def run!
|
115
|
-
puts "Jabbot #{Jabbot::VERSION} imposing as #{login} on #{channel}@#{server}"
|
135
|
+
puts "Jabbot #{Jabbot::VERSION} imposing as #{config.login} on #{config.channel}@#{config.server}"
|
116
136
|
|
117
137
|
onclose_block = proc {
|
118
138
|
close
|
@@ -121,11 +141,11 @@ module Jabbot
|
|
121
141
|
}
|
122
142
|
|
123
143
|
Kernel.trap(:INT, onclose_block)
|
124
|
-
Kernel.trap(:QUIT, onclose_block)
|
144
|
+
Kernel.trap(:QUIT, onclose_block) rescue nil
|
125
145
|
|
126
|
-
debug! if config
|
146
|
+
debug! if config.debug
|
127
147
|
|
128
|
-
#
|
148
|
+
# Connect the bot and keep it running.
|
129
149
|
EventMachine.run do
|
130
150
|
connect
|
131
151
|
|
@@ -175,13 +195,13 @@ module Jabbot
|
|
175
195
|
# * leaves
|
176
196
|
# * subject changes
|
177
197
|
#
|
178
|
-
# Returs
|
198
|
+
# Returs a Proc to be called to assign the handlers.
|
179
199
|
def muc_handlers
|
180
200
|
Proc.new do |muc|
|
181
201
|
muc.on_message do |time, nick, text|
|
182
|
-
if time.nil?
|
202
|
+
if time.nil? # Don't process messages from the past.
|
183
203
|
begin
|
184
|
-
dispatch_messages(:message, [Message.new(nick, text, Time.now, :public)]) unless nick == config
|
204
|
+
dispatch_messages(:message, [Message.new(nick, text, Time.now, :public)]) unless nick == config.nick
|
185
205
|
rescue Exception => boom
|
186
206
|
log.fatal boom.inspect
|
187
207
|
log.fatal boom.backtrace[0..5].join("\n")
|
@@ -190,9 +210,9 @@ module Jabbot
|
|
190
210
|
end
|
191
211
|
|
192
212
|
muc.on_private_message do |time, nick, text|
|
193
|
-
if time.nil?
|
213
|
+
if time.nil? # Don't process messages from the past.
|
194
214
|
begin
|
195
|
-
dispatch_messages(:private, [Message.new(nick, text, Time.now, :
|
215
|
+
dispatch_messages(:private, [Message.new(nick, text, Time.now, :private)]) unless nick == config.nick
|
196
216
|
rescue Exception => boom
|
197
217
|
log.fatal boom.inspect
|
198
218
|
log.fatal boom.backtrace[0..5].join("\n")
|
@@ -204,9 +224,9 @@ module Jabbot
|
|
204
224
|
unless @users.include? nick
|
205
225
|
@users << nick
|
206
226
|
end
|
207
|
-
if time.nil?
|
227
|
+
if time.nil? # Don't process messages from the past.
|
208
228
|
begin
|
209
|
-
dispatch_messages(:join, [Message.new(nick, "join", Time.now, :join)]) unless nick == config
|
229
|
+
dispatch_messages(:join, [Message.new(nick, "join", Time.now, :join)]) unless nick == config.nick
|
210
230
|
rescue Exception => boom
|
211
231
|
log.fatal boom.inspect
|
212
232
|
log.fatal boom.backtrace[0..5].join("\n")
|
@@ -216,7 +236,7 @@ module Jabbot
|
|
216
236
|
|
217
237
|
muc.on_leave do |time, nick|
|
218
238
|
@users.delete(nick)
|
219
|
-
if time.nil?
|
239
|
+
if time.nil? # Don't process messages from the past.
|
220
240
|
begin
|
221
241
|
dispatch_messages(:leave, [Message.new(nick, "leave", Time.now, :leave)])
|
222
242
|
rescue Exception => boom
|
@@ -227,7 +247,7 @@ module Jabbot
|
|
227
247
|
end
|
228
248
|
|
229
249
|
muc.on_subject do |time, nick, subject|
|
230
|
-
if time.nil?
|
250
|
+
if time.nil? # Don't process messages from the past.
|
231
251
|
begin
|
232
252
|
dispatch_messages(:subject, [Message.new(nick, subject, Time.now, :subject)])
|
233
253
|
rescue Exception => boom
|
@@ -239,7 +259,7 @@ module Jabbot
|
|
239
259
|
end
|
240
260
|
end
|
241
261
|
|
242
|
-
# Dispatch a collection of messages.
|
262
|
+
# Internal: Dispatch a collection of messages.
|
243
263
|
#
|
244
264
|
# type - The Symbol type to be processed.
|
245
265
|
# messages - An Array of String messages to be dispatched.
|
@@ -255,9 +275,9 @@ module Jabbot
|
|
255
275
|
# Returns logger instance.
|
256
276
|
def log
|
257
277
|
return @log if @log
|
258
|
-
os = config
|
278
|
+
os = config.log_file ? File.open(config.log_file, "a") : $stdout
|
259
279
|
@log = Logger.new(os)
|
260
|
-
@log.level = Logger.const_get(config
|
280
|
+
@log.level = Logger.const_get(config.log_level ? config.log_level.upcase : "INFO")
|
261
281
|
@log
|
262
282
|
end
|
263
283
|
|
@@ -266,26 +286,20 @@ module Jabbot
|
|
266
286
|
# Returns the configure Hash.
|
267
287
|
def configure
|
268
288
|
yield @config
|
269
|
-
@conf = @config.to_hash
|
270
|
-
end
|
271
|
-
|
272
|
-
# Internal: Maps configuration settings to real methods.
|
273
|
-
#
|
274
|
-
# Returns the value of the configuration setting
|
275
|
-
# or nil if none is found.
|
276
|
-
def method_missing(name, *args, &block)
|
277
|
-
return super unless config.key?(name)
|
278
|
-
|
279
|
-
self.class.send(:define_method, name) { config[name] }
|
280
|
-
config[name]
|
281
289
|
end
|
282
290
|
|
283
291
|
# Public: Get the current configuration settings.
|
284
292
|
#
|
285
293
|
# Returns the configuration Hash.
|
286
294
|
def config
|
287
|
-
|
288
|
-
|
295
|
+
@config
|
296
|
+
end
|
297
|
+
|
298
|
+
# Public: Easy access to the bot's nickname
|
299
|
+
#
|
300
|
+
# Returns the configured nick String.
|
301
|
+
def nick
|
302
|
+
@config.nick
|
289
303
|
end
|
290
304
|
end
|
291
305
|
end
|
data/lib/jabbot/config.rb
CHANGED
@@ -1,108 +1,80 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
|
3
1
|
module Jabbot
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
2
|
+
# Default configuration values.
|
3
|
+
# If an option is not set on creation,
|
4
|
+
# it gets the default value instead.
|
5
|
+
DEFAULT_CONFIG = {
|
6
|
+
:login => nil,
|
7
|
+
:password => nil,
|
8
|
+
:nick => 'jabbot',
|
9
|
+
:server => nil,
|
10
|
+
:channel => nil,
|
11
|
+
:channel_password => nil,
|
12
|
+
:resource => 'jabbot',
|
13
|
+
:log_level => 'info',
|
14
|
+
:log_file => nil,
|
15
|
+
:debug => false
|
16
|
+
}
|
17
|
+
|
18
|
+
# The main configuration of Jabbot.
|
19
|
+
# It's nothing more than a simple struct of key-value pairs.
|
7
20
|
#
|
8
|
-
#
|
9
|
-
# config << Jabbot::CliConfig.new
|
10
|
-
# config.to_hash
|
21
|
+
# Examples:
|
11
22
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
23
|
+
# Jabbot::Config.new({:login => "jabbot@server.com", :password => "secret",
|
24
|
+
# :debug => true})
|
25
|
+
# # => #<struct Jabbot::Config login="jabbot@server.com", password="secret",
|
26
|
+
# nick="jabbot", server=nil, channel=nil, resource="jabbot",
|
27
|
+
# log_level="info", log_file=nil, debug=true>
|
17
28
|
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
29
|
+
# Jabbot::Config.new("jabbot@server.com", "secret")
|
30
|
+
# # => #<struct Jabbot::Config login="jabbot@server.com", password="secret",
|
31
|
+
# nick="jabbot", server=nil, channel=nil, resource="jabbot",
|
32
|
+
# log_level="info", log_file=nil, debug=false>
|
33
|
+
#
|
34
|
+
# config.login
|
35
|
+
# # => "jabbot@server.com"
|
36
|
+
# config.channel
|
37
|
+
# # => nil
|
38
|
+
# config.channel = "room@conference.server.com"
|
39
|
+
# # => "room@conference.server.com"
|
40
|
+
#
|
41
|
+
Config = Struct.new(
|
42
|
+
# We need the correct order here, so this is done manually.
|
43
|
+
:login,
|
44
|
+
:password,
|
45
|
+
:nick,
|
46
|
+
:server,
|
47
|
+
:channel,
|
48
|
+
:channel_password,
|
49
|
+
:resource,
|
50
|
+
:log_level,
|
51
|
+
:log_file,
|
52
|
+
:debug
|
53
|
+
) do
|
54
|
+
# Public: Initialize new configuration object.
|
41
55
|
#
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
56
|
+
# *args - Any number of valid arguments passed to the super class.
|
57
|
+
# If there is only one argument and it is kind of a Hash,
|
58
|
+
# it is treated as the key-value pairs are the options.
|
59
|
+
# If there is a default value for an option key,
|
60
|
+
# it is set if needed.
|
61
|
+
def initialize(*args)
|
62
|
+
# First: call the super class.
|
63
|
+
super
|
48
64
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# name, *args and &block as described in the core classes.
|
53
|
-
#
|
54
|
-
# Returns the configuration value if any.
|
55
|
-
def method_missing(name, *args, &block)
|
56
|
-
regex = /=$/
|
57
|
-
attr_name = name.to_s.sub(regex, '').to_sym
|
58
|
-
return super if name == attr_name && !@settings.key?(attr_name)
|
65
|
+
# If we got a hash, treat it as the configuration options.
|
66
|
+
if args.size == 1 && args.first.kind_of?(Hash)
|
67
|
+
self.login = nil # Reset first value.
|
59
68
|
|
60
|
-
|
61
|
-
|
69
|
+
args.first.each do |key, value|
|
70
|
+
send("#{key}=", value)
|
71
|
+
end
|
62
72
|
end
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# Public: Merges configurations and returns a hash with all options
|
68
|
-
#
|
69
|
-
# Returns a Hash of the configuration.
|
70
|
-
def to_hash
|
71
|
-
hash = {}.merge(@settings)
|
72
|
-
@configs.each { |conf| hash.merge!(conf.to_hash) }
|
73
|
-
hash
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.default
|
77
|
-
Config.new({}.merge(DEFAULT))
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Deprecated: Configuration from files
|
82
|
-
class FileConfig < Config
|
83
|
-
# Public: Initializes a new FileConfig object.
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# fos - Accepts a Stream or a String filename to read configuration from
|
87
|
-
# (default: "./config/bot.yml")
|
88
|
-
# If a stream is passed it is not closed from within the method.
|
89
|
-
def initialize(fos = File.expand_path("config/bot.yml"))
|
90
|
-
warn "Jabbot::FileConfig is deprecated and will be removed in the next version."
|
91
|
-
|
92
|
-
stream = fos.is_a?(String) ? File.open(fos, "r") : fos
|
93
|
-
|
94
|
-
begin
|
95
|
-
config = YAML.load(stream.read)
|
96
|
-
config.symbolize_keys! if config
|
97
|
-
rescue Exception => err
|
98
|
-
puts err.message
|
99
|
-
puts "Unable to load configuration, aborting"
|
100
|
-
exit
|
101
|
-
ensure
|
102
|
-
stream.close if fos.is_a?(String)
|
74
|
+
# Set defaults.
|
75
|
+
DEFAULT_CONFIG.each do |key, value|
|
76
|
+
self.send(key.to_s) || self.send("#{key}=", value)
|
103
77
|
end
|
104
|
-
|
105
|
-
super config.is_a?(Hash) ? config : {}
|
106
78
|
end
|
107
79
|
end
|
108
80
|
end
|
data/lib/jabbot/handlers.rb
CHANGED
@@ -29,21 +29,11 @@ module Jabbot
|
|
29
29
|
@handlers ||= {
|
30
30
|
:message => [],
|
31
31
|
:private => [],
|
32
|
-
:join
|
32
|
+
:join => [],
|
33
33
|
:subject => [],
|
34
|
-
:leave
|
34
|
+
:leave => []
|
35
35
|
}
|
36
36
|
end
|
37
|
-
|
38
|
-
# Deprecated: Set the handler types and Arrays
|
39
|
-
#
|
40
|
-
# hash - A hash containing the handler types and associated Arrays
|
41
|
-
# (see `handlers`).
|
42
|
-
#
|
43
|
-
# Returns nothing.
|
44
|
-
def handlers=(hash)
|
45
|
-
@handlers = hash
|
46
|
-
end
|
47
37
|
end
|
48
38
|
|
49
39
|
# A Handler consists of a pattern to match a given message,
|
@@ -171,9 +161,9 @@ module Jabbot
|
|
171
161
|
attr_reader :pattern
|
172
162
|
|
173
163
|
# Internal: Determines if this handler is suited to handle
|
174
|
-
#
|
164
|
+
# a message.
|
175
165
|
#
|
176
|
-
# Returns
|
166
|
+
# Returns true if it recognized the given message, false otherwise.
|
177
167
|
def recognize?(message)
|
178
168
|
return false if @pattern && message.text !~ @pattern
|
179
169
|
|
@@ -209,6 +199,8 @@ module Jabbot
|
|
209
199
|
# message - The incoming String message.
|
210
200
|
# params - The hash containing matched tokens.
|
211
201
|
#
|
202
|
+
# Both arguments are passed to the underlying handler block.
|
203
|
+
#
|
212
204
|
# Returns the return from the handler block.
|
213
205
|
def handle(message, params)
|
214
206
|
@handler.call(message, params) if @handler
|
data/test/helper.rb
CHANGED
@@ -9,36 +9,6 @@ $LOAD_PATH.unshift(dir)
|
|
9
9
|
|
10
10
|
require 'jabbot'
|
11
11
|
|
12
|
-
module Test::Unit::Assertions
|
13
|
-
def assert_hashes_equal(expected, actual, message = nil)
|
14
|
-
full_message = build_message(message, <<EOT, expected.inspect, actual.inspect)
|
15
|
-
<?> expected but was
|
16
|
-
<?>.
|
17
|
-
EOT
|
18
|
-
assert_block(full_message) do
|
19
|
-
break false if expected.keys.length != actual.keys.length
|
20
|
-
expected.keys.all? { |k| expected[k] == actual[k] }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def assert_hashes_not_equal(expected, actual, message = nil)
|
25
|
-
full_message = build_message(message, <<EOT, expected.inspect, actual.inspect)
|
26
|
-
<?> expected but was
|
27
|
-
<?>.
|
28
|
-
EOT
|
29
|
-
assert_block(full_message) do
|
30
|
-
break false if expected.keys.length != actual.keys.length
|
31
|
-
expected.keys.any? { |k| expected[k] != actual[k] }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
TEST_DIR = File.join(File.dirname(__FILE__), *%w[.])
|
37
|
-
|
38
|
-
def testpath(path)
|
39
|
-
File.join(TEST_DIR, path)
|
40
|
-
end
|
41
|
-
|
42
12
|
# test/spec/mini 3
|
43
13
|
# http://gist.github.com/25455
|
44
14
|
# chris@ozmm.org
|
@@ -46,7 +16,7 @@ end
|
|
46
16
|
def context(*args, &block)
|
47
17
|
return super unless (name = args.first) && block
|
48
18
|
require 'test/unit'
|
49
|
-
klass = Class.new(
|
19
|
+
klass = Class.new(Test::Unit::TestCase) do
|
50
20
|
def self.test(name, &block)
|
51
21
|
define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
|
52
22
|
end
|
data/test/test_bot.rb
CHANGED
@@ -2,49 +2,21 @@ require 'helper'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
context "Bot" do
|
5
|
-
test "raise no exceptions when initialized" do
|
6
|
-
assert_nothing_raised do
|
7
|
-
Jabbot::Bot.new Jabbot::Config.new
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
test "raise exception when initialized without config file" do
|
12
|
-
assert_raise SystemExit do
|
13
|
-
Jabbot::Bot.new
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
test "raise no exception on initialize when config file exists" do
|
18
|
-
if File.exists?("config")
|
19
|
-
FileUtils.rm("config/bot.yml")
|
20
|
-
else
|
21
|
-
FileUtils.mkdir("config")
|
22
|
-
end
|
23
|
-
|
24
|
-
File.open("config/bot.yml", "w") { |f| f.puts "" }
|
25
|
-
|
26
|
-
assert_nothing_raised do
|
27
|
-
Jabbot::Bot.new
|
28
|
-
end
|
29
|
-
|
30
|
-
FileUtils.rm_rf("config")
|
31
|
-
end
|
32
|
-
|
33
5
|
test "provide configuration settings as methods" do
|
34
|
-
bot = Jabbot::Bot.new
|
35
|
-
assert_equal "jabbot", bot.login
|
6
|
+
bot = Jabbot::Bot.new :login => "jabbot"
|
7
|
+
assert_equal "jabbot", bot.config.login
|
36
8
|
end
|
37
9
|
|
38
10
|
test "return logger instance" do
|
39
|
-
bot = Jabbot::Bot.new
|
11
|
+
bot = Jabbot::Bot.new
|
40
12
|
assert bot.log.is_a?(Logger)
|
41
13
|
end
|
42
14
|
|
43
15
|
test "respect configured log level" do
|
44
|
-
bot = Jabbot::Bot.new(
|
16
|
+
bot = Jabbot::Bot.new(:log_level => "info")
|
45
17
|
assert_equal Logger::INFO, bot.log.level
|
46
18
|
|
47
|
-
bot = Jabbot::Bot.new(
|
19
|
+
bot = Jabbot::Bot.new(:log_level => "warn")
|
48
20
|
assert_equal Logger::WARN, bot.log.level
|
49
21
|
end
|
50
22
|
end
|
data/test/test_config.rb
CHANGED
@@ -2,80 +2,19 @@ require 'helper'
|
|
2
2
|
require 'stringio'
|
3
3
|
|
4
4
|
context "Config" do
|
5
|
-
test "default
|
6
|
-
assert_not_nil Jabbot::Config::DEFAULT
|
7
|
-
assert Jabbot::Config::DEFAULT.is_a?(Hash)
|
8
|
-
end
|
9
|
-
|
10
|
-
test "initialize with no options" do
|
11
|
-
assert_hashes_equal({}, Jabbot::Config.new.settings)
|
12
|
-
end
|
13
|
-
|
14
|
-
test "return config from add" do
|
15
|
-
config = Jabbot::Config.new
|
16
|
-
assert_equal config, config.add(Jabbot::Config.new)
|
17
|
-
end
|
18
|
-
|
19
|
-
test "alias add to <<" do
|
5
|
+
test "default config is set" do
|
20
6
|
config = Jabbot::Config.new
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
test "mirror method_missing as config getters" do
|
26
|
-
config = Jabbot::Config.default << Jabbot::Config.new
|
27
|
-
assert_equal Jabbot::Config::DEFAULT[:password], config.password
|
28
|
-
assert_equal Jabbot::Config::DEFAULT[:login], config.login
|
7
|
+
assert_equal Jabbot::DEFAULT_CONFIG[:password], config.password
|
8
|
+
assert_equal Jabbot::DEFAULT_CONFIG[:login], config.login
|
29
9
|
end
|
30
10
|
|
31
11
|
test "mirror missing methods as config setters" do
|
32
|
-
config = Jabbot::Config.
|
33
|
-
assert_equal Jabbot::
|
12
|
+
config = Jabbot::Config.new
|
13
|
+
assert_equal Jabbot::DEFAULT_CONFIG[:login], config.login
|
34
14
|
|
35
15
|
val = "jabbot"
|
36
16
|
config.login = val+'!'
|
37
|
-
assert_not_equal Jabbot::
|
17
|
+
assert_not_equal Jabbot::DEFAULT_CONFIG[:login], config.login
|
38
18
|
assert_equal val+'!', config.login
|
39
19
|
end
|
40
|
-
|
41
|
-
test "not override default hash" do
|
42
|
-
config = Jabbot::Config.default
|
43
|
-
hash = Jabbot::Config::DEFAULT
|
44
|
-
|
45
|
-
config.login = "jabbot"
|
46
|
-
config.password = "secret"
|
47
|
-
|
48
|
-
assert_hashes_not_equal Jabbot::Config::DEFAULT, config.to_hash
|
49
|
-
assert_hashes_equal hash, Jabbot::Config::DEFAULT
|
50
|
-
end
|
51
|
-
|
52
|
-
test "return merged configuration from to_hash" do
|
53
|
-
config = Jabbot::Config.new
|
54
|
-
config.login = "jabbot"
|
55
|
-
config.password = "secret"
|
56
|
-
|
57
|
-
config2 = Jabbot::Config.new({})
|
58
|
-
config2.login = "not_jabbot2"
|
59
|
-
config << config2
|
60
|
-
options = config.to_hash
|
61
|
-
|
62
|
-
assert_equal "secret", options[:password]
|
63
|
-
assert_equal "not_jabbot2", options[:login]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context "FileConfig" do
|
68
|
-
test "subclass config for file config" do
|
69
|
-
assert Jabbot::FileConfig.new(StringIO.new).is_a?(Jabbot::Config)
|
70
|
-
end
|
71
|
-
|
72
|
-
test "read settings from stream" do
|
73
|
-
config = Jabbot::FileConfig.new(StringIO.new <<-YAML)
|
74
|
-
login: jabbot
|
75
|
-
password: secret
|
76
|
-
YAML
|
77
|
-
|
78
|
-
assert_equal "jabbot", config.login
|
79
|
-
assert_equal "secret", config.password
|
80
|
-
end
|
81
20
|
end
|
data/test/test_macros.rb
CHANGED
@@ -6,7 +6,7 @@ context "Macros" do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
test "yield configuration" do
|
9
|
-
Jabbot::Macros.bot = Jabbot::Bot.new
|
9
|
+
Jabbot::Macros.bot = Jabbot::Bot.new
|
10
10
|
|
11
11
|
conf = nil
|
12
12
|
assert_nothing_raised { configure { |c| conf = c } }
|
@@ -14,7 +14,7 @@ context "Macros" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
test "add handler" do
|
17
|
-
Jabbot::Macros.bot = Jabbot::Bot.new
|
17
|
+
Jabbot::Macros.bot = Jabbot::Bot.new
|
18
18
|
|
19
19
|
handler = add_handler(:message, ":command", :from => :cjno)
|
20
20
|
assert handler.is_a?(Jabbot::Handler)
|
metadata
CHANGED
@@ -1,102 +1,111 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: jabbot
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.3.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- badboy
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
17
14
|
name: xmpp4r
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: "0.4"
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
25
20
|
type: :runtime
|
26
|
-
version_requirements: *id001
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: eventmachine
|
29
21
|
prerelease: false
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: eventmachine
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.12'
|
36
34
|
type: :runtime
|
37
|
-
version_requirements: *id002
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: shoulda
|
40
35
|
prerelease: false
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: shoulda
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
46
47
|
version: 2.10.1
|
47
48
|
type: :development
|
48
|
-
|
49
|
-
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.10.1
|
55
|
+
description: |2
|
56
|
+
Jabbot is a Ruby micro-framework for creating Jabber/MUC bots,
|
57
|
+
heavily inspired by Sinatra and Twibot.
|
58
|
+
|
59
|
+
I modified the code of Twibot to fit my needs.
|
60
|
+
The original Twibot code by Christian Johansen is located at:
|
61
|
+
http://github.com/cjohansen/twibot
|
62
|
+
|
63
|
+
It's as easy as definig a small message handler:
|
64
|
+
message {|message, params|
|
65
|
+
post message.text
|
66
|
+
}
|
50
67
|
email: badboy@archlinux.us
|
51
68
|
executables: []
|
52
|
-
|
53
69
|
extensions: []
|
54
|
-
|
55
70
|
extra_rdoc_files: []
|
56
|
-
|
57
|
-
|
71
|
+
files:
|
72
|
+
- LICENSE
|
58
73
|
- README.md
|
59
74
|
- Rakefile
|
60
|
-
- LICENSE
|
61
75
|
- lib/hash.rb
|
62
76
|
- lib/jabbot.rb
|
63
|
-
- lib/jabbot/
|
77
|
+
- lib/jabbot/bot.rb
|
64
78
|
- lib/jabbot/config.rb
|
65
79
|
- lib/jabbot/handlers.rb
|
66
|
-
- lib/jabbot/
|
67
|
-
-
|
68
|
-
- test/test_macros.rb
|
69
|
-
- test/test_bot.rb
|
80
|
+
- lib/jabbot/macros.rb
|
81
|
+
- lib/jabbot/version.rb
|
70
82
|
- test/helper.rb
|
83
|
+
- test/test_bot.rb
|
84
|
+
- test/test_config.rb
|
71
85
|
- test/test_handler.rb
|
72
86
|
- test/test_hash.rb
|
73
|
-
|
87
|
+
- test/test_macros.rb
|
74
88
|
homepage: http://github.com/badboy/jabbot
|
75
89
|
licenses: []
|
76
|
-
|
90
|
+
metadata: {}
|
77
91
|
post_install_message:
|
78
92
|
rdoc_options: []
|
79
|
-
|
80
|
-
require_paths:
|
93
|
+
require_paths:
|
81
94
|
- lib
|
82
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
|
84
|
-
requirements:
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
85
97
|
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version:
|
88
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
|
90
|
-
requirements:
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
91
102
|
- - ">="
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version:
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
94
105
|
requirements: []
|
95
|
-
|
96
106
|
rubyforge_project:
|
97
|
-
rubygems_version:
|
107
|
+
rubygems_version: 2.2.2
|
98
108
|
signing_key:
|
99
|
-
specification_version:
|
109
|
+
specification_version: 4
|
100
110
|
summary: Simple framework for creating Jabber/MUC bots, inspired by Sinatra and Twibot
|
101
111
|
test_files: []
|
102
|
-
|