jabbot 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 quite some time now
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
- ## Usage
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
- # Receive messages, and post them publicly
24
- message do |message, params|
25
- post message.text
26
- end
17
+ ## Usage
27
18
 
28
- # Respond to query if they come from the right crowd
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
- # Log every single line
36
- # (you can use "message :all" too ;)
37
- message do |message, params|
38
- MyApp.log_message(message)
39
- end
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
- ruby bot.rb
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
- _Deprecated: The option to configure by YAML files will be removed in the next stable release._
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
- login: jabber_login
57
- password: jabber_password
58
- channel: channel_to_join
59
- server: server_to_connect_to
60
- nick: mybot
62
+ ~~~ruby
63
+ configure do |conf|
64
+ conf.login = "my_account"
65
+ conf.nick = "mybot"
66
+ end
67
+ ~~~
61
68
 
62
- You can also configure with Ruby:
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
- configure do |conf|
65
- conf.login = "my_account"
66
- conf.nick = "mybot"
67
- do
71
+ ~~~ruby
72
+ configure do |conf|
73
+ conf.resource ="mybot_resource"
74
+ end
75
+ ~~~
68
76
 
69
- If you don't specify login and/or password in any of these ways, Jabbot will fail
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
- message /^time ([^\s]*) ([^\s]*)/ do |message, params|
95
- # params is an array of matches when using regexp routes
96
- time = MyTimeService.lookup(params[0], params[1])
97
- post "Time is #{time} in #{params[:city]}, #{params[:country]}"
98
- end
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
- message :exact => "pattern" do |message, params|
103
- ...
104
- end
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
- You can get it via rubygems:
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
- gem install jabbot
122
+ ~~~
123
+ gem install jabbot
124
+ ~~~
122
125
 
123
126
  ## Is it Ruby 1.9?
124
127
 
125
- All tests passes on Ruby 1.9.
126
- Seems like it works :)
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
@@ -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
@@ -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 (default: nil).
36
- def initialize(options=nil)
37
- @conf = nil
38
- @config = options || Jabbot::Config.default << Jabbot::FileConfig.new
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, put that in the right text field. Remove the slash!"
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[:resource] || "jabbot"
80
- @mucjid.resource = config[:nick] || "jabbot"
81
- @users << config[:nick]
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[:debug]
146
+ debug! if config.debug
127
147
 
128
- # connect the bot and keep it running
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 nothing.
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[:nick]
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, :query)]) unless nick == config[:nick]
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[:nick]
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[:log_file] ? File.open(config[:log_file], "a") : $stdout
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[:log_level] ? config[:log_level].upcase : "INFO")
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
- return @conf if @conf
288
- @conf = @config.to_hash
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
@@ -1,108 +1,80 @@
1
- require 'optparse'
2
-
3
1
  module Jabbot
4
- # Jabbot configuration. Use either Jabbot::CliConfig.new or
5
- # JabbotFileConfig.new setup a new bot from either command line or file
6
- # (respectively). Configurations can be chained so they override each other:
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
- # config = Jabbot::FileConfig.new
9
- # config << Jabbot::CliConfig.new
10
- # config.to_hash
21
+ # Examples:
11
22
  #
12
- # The preceding example will create a configuration which is based on a
13
- # configuration file but have certain values overridden from the command line.
14
- # This can be used for instance to store everything but the Twitter account
15
- # password in your configuration file. Then you can just provide the password
16
- # when running the bot.
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
- class Config
19
- attr_reader :settings
20
-
21
- DEFAULT = {
22
- :log_level => 'info',
23
- :log_file => nil,
24
- :login => nil,
25
- :password => nil,
26
- :nick => 'jabbot',
27
- :channel => nil,
28
- :server => nil,
29
- :resource => nil,
30
- :debug => false
31
- }
32
-
33
- def initialize(settings = {})
34
- @configs = []
35
- @settings = settings
36
- end
37
-
38
- # Public: Add a configuration object to override given settings
39
- #
40
- # config -
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
- # Returns the class object.
43
- def add(config)
44
- @configs << config
45
- self
46
- end
47
- alias_method :<<, :add
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
- # Internal: Maps calls to non existant functions to
50
- # configuration values, if they exist.
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
- if name != attr_name
61
- @settings[attr_name] = args.first
69
+ args.first.each do |key, value|
70
+ send("#{key}=", value)
71
+ end
62
72
  end
63
73
 
64
- @settings[attr_name]
65
- end
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
@@ -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
- # an incoming message.
164
+ # a message.
175
165
  #
176
- # Returns a Boolean if it recognized the given message.
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
@@ -0,0 +1,3 @@
1
+ module Jabbot
2
+ VERSION = '1.0.0'
3
+ end
@@ -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(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
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
@@ -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 Jabbot::Config.new(:login => "jabbot")
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(Jabbot::Config.default << Jabbot::Config.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(Jabbot::Config.new(:log_level => "info"))
16
+ bot = Jabbot::Bot.new(:log_level => "info")
45
17
  assert_equal Logger::INFO, bot.log.level
46
18
 
47
- bot = Jabbot::Bot.new(Jabbot::Config.new(:log_level => "warn"))
19
+ bot = Jabbot::Bot.new(:log_level => "warn")
48
20
  assert_equal Logger::WARN, bot.log.level
49
21
  end
50
22
  end
@@ -2,80 +2,19 @@ require 'helper'
2
2
  require 'stringio'
3
3
 
4
4
  context "Config" do
5
- test "default configuration be a hash" do
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
- assert config.respond_to?(:<<)
22
- assert config << Jabbot::Config.new
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.default << Jabbot::Config.new
33
- assert_equal Jabbot::Config::DEFAULT[:login], config.login
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::Config::DEFAULT[:login], config.login
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
@@ -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 Jabbot::Config.default
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 Jabbot::Config.default
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
- prerelease:
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
- date: 2011-06-25 00:00:00 +02:00
14
- default_executable:
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
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
20
- none: false
21
- requirements:
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
- requirement: &id002 !ruby/object:Gem::Requirement
31
- none: false
32
- requirements:
33
- - - ~>
34
- - !ruby/object:Gem::Version
35
- version: "0.12"
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
- requirement: &id003 !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
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
- version_requirements: *id003
49
- description: " Jabbot is a Ruby micro-framework for creating Jabber/MUC bots,\n heavily inspired by Sinatra and Twibot.\n\n I modified the code of Twibot to fit my needs.\n The original Twibot code by Christian Johansen is located at:\n http://github.com/cjohansen/twibot\n\n It's as easy as definig a small message handler:\n message {|message, params|\n post message.text\n }\n"
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
- files:
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/macros.rb
77
+ - lib/jabbot/bot.rb
64
78
  - lib/jabbot/config.rb
65
79
  - lib/jabbot/handlers.rb
66
- - lib/jabbot/bot.rb
67
- - test/test_config.rb
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
- has_rdoc: true
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
- none: false
84
- requirements:
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
85
97
  - - ">="
86
- - !ruby/object:Gem::Version
87
- version: "0"
88
- required_rubygems_version: !ruby/object:Gem::Requirement
89
- none: false
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: "0"
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
94
105
  requirements: []
95
-
96
106
  rubyforge_project:
97
- rubygems_version: 1.6.2
107
+ rubygems_version: 2.2.2
98
108
  signing_key:
99
- specification_version: 3
109
+ specification_version: 4
100
110
  summary: Simple framework for creating Jabber/MUC bots, inspired by Sinatra and Twibot
101
111
  test_files: []
102
-