jabbot 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009-2010 Jan-Erik Rediger (badboy\_)
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.
@@ -0,0 +1,157 @@
1
+ # Jabbot
2
+
3
+ Official URL: http://github.com/badboy/jabbot/tree/master
4
+ Jan-Erik Rediger (badboy\_) (http://badboy.pytalhost.de)
5
+
6
+ ## Description
7
+
8
+ Jabbot is a Ruby micro-framework for creating Jabber/MUC bots,
9
+ heavily inspired by Sinatra and Twibot.
10
+
11
+ I modified the code of Twibot to fit my needs.
12
+ The original Twibot code is located at:
13
+ http://github.com/cjohansen/twibot/tree/master
14
+
15
+ A big thank you to Christian Johansen, who wrote the code for Twibot.
16
+ Jabbot is heavily based on his code.
17
+
18
+ ## Usage
19
+
20
+ ### Simple example
21
+
22
+ # Receive messages, and post them publicly
23
+ message do |message, params|
24
+ post message.text
25
+ end
26
+
27
+ # Respond to query if they come from the right crowd
28
+ # post "message" => "user" is just some syntax sugar
29
+ # post "message", "user" will work to
30
+ query :from => [:cjno, :irbno] do |message, params|
31
+ post "#{message.user} I agree" => message.user
32
+ end
33
+
34
+ # Log every single line
35
+ # (you can use "message :all" too ;)
36
+ message do |message, params|
37
+ MyApp.log_message(message)
38
+ end
39
+
40
+ ### Running the bot
41
+
42
+ To run the bot, simply do:
43
+
44
+ ruby bot.rb
45
+
46
+ Jabbot uses the [at\_exit hook](http://ruby-doc.org/core/classes/Kernel.html#M005932) to start.
47
+
48
+ ### Configuration
49
+
50
+ Jabbot looks for a configuration file in ./config/bot.yml. It should contain
51
+ atleast:
52
+
53
+ login: jabber_login
54
+ password: jabber_password
55
+ channel: channel_to_join
56
+ server: server_to_connect_to
57
+ nick: mybot
58
+
59
+ You can also configure with Ruby:
60
+
61
+ configure do |conf|
62
+ conf.login = "my_account"
63
+ conf.nick = "mybot"
64
+ do
65
+
66
+ If you don't specify login and/or password in any of these ways, Jabbot will fail
67
+ Nick is automatically set to "jabbot" unless something different is defined
68
+ If you want you can set the Jabber Resource:
69
+
70
+ configure do |conf|
71
+ conf.resource ="mybot_resource"
72
+
73
+ end
74
+
75
+ Default is "jabbot".
76
+
77
+ ### "Routes"
78
+
79
+ Like Sinatra, and other web app frameworks, Jabbot supports "routes":
80
+ patterns to match incoming tweets and messages:
81
+
82
+ message "time :country :city" do |message, params|
83
+ time = MyTimeService.lookup(params[:country], params[:city])
84
+ post "Time is #{time} in #{params[:city]}, #{params[:country]}"
85
+ end
86
+
87
+ You can have several "message" blocks (or "join", "leave", "query" or "subject").
88
+ Every matching block will be called.
89
+
90
+ Jabbot also supports regular expressions as routes:
91
+
92
+ message /^time ([^\s]*) ([^\s]*)/ do |message, params|
93
+ # params is an array of matches when using regexp routes
94
+ time = MyTimeService.lookup(params[0], params[1])
95
+ post "Time is #{time} in #{params[:city]}, #{params[:country]}"
96
+ end
97
+
98
+ ## Requirements
99
+
100
+ xmpp4r. You'll need atleast 0.4.
101
+ You can get it via rubygems:
102
+
103
+ gem install xmpp4r
104
+
105
+ or get it from: http://home.gna.org/xmpp4r/
106
+
107
+ ## Installation
108
+
109
+ Jabbot is available via gem:
110
+
111
+ gem install jabbot
112
+
113
+ ## Is it Ruby 1.9?
114
+
115
+ All tests passes on Ruby 1.9.
116
+ Seems like it works :)
117
+
118
+ ## Samples
119
+
120
+ There are two examples in the [samples][] directory:
121
+
122
+ * [jabbot_example.rb][] is a working sample without real functionality.
123
+ * [black.rb][] is the code I use for my own bot (without the config of course).
124
+
125
+ ## Contributors
126
+
127
+ * Christian Johansen (cjohansen) (author of Twibot) - http://www.cjohansen.no
128
+
129
+ ## License
130
+
131
+ The code is released under the MIT license. See [LICENSE][].
132
+
133
+ ## Contribute
134
+
135
+ If you'd like to hack on jabbot, start by forking my repo on GitHub:
136
+
137
+ http://github.com/badboy/jabbot
138
+
139
+ jabbot needs xmpp4r, so just install it:
140
+
141
+ gem install xmpp4r
142
+
143
+ Then:
144
+
145
+ 1. Clone down your fork
146
+ 2. Create a thoughtfully named topic branch to contain your change
147
+ 3. Hack away
148
+ 4. Add tests and make sure everything still passes by running `rake`
149
+ 5. If you are adding new functionality, document it in the README
150
+ 6. Do not change the version number, I will do that on my end
151
+ 7. If necessary, rebase your commits into logical chunks, without errors
152
+ 8. Push the branch up to GitHub
153
+ 9. Send me (badboy) a pull request for your branch
154
+
155
+ [LICENSE]: http://github.com/badboy/jabbot/blob/master/LICENSE
156
+ [jabbot_example.rb]: http://github.com/badboy/jabbot/blob/master/samples/jabbot_example.rb
157
+ [black.rb]: http://github.com/badboy/jabbot/blob/master/samples/black.rb
data/Rakefile CHANGED
@@ -1,24 +1,11 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
1
  begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "jabbot"
8
- gem.summary = %Q{Simple framework for creating Jabber/MUC bots, inspired by Sinatra and Twibot}
9
- gem.email = "badboy@archlinux.us"
10
- gem.homepage = "http://github.com/badboy/jabbot"
11
- gem.authors = ["BadBoy_"]
12
- gem.add_dependency('xmpp4r', '>=0.4')
13
- gem.add_development_dependency('thoughtbot-shoulda', '>=2.10.1')
14
- gem.add_development_dependency('jeweler', '>=0.10.2')
15
-
16
- gem.rubyforge_project = 'jabbot'
17
- end
2
+ require 'mg'
18
3
  rescue LoadError
19
- puts "Jeweler not available. Install it with: sudo gem install jeweler"
4
+ abort "Please `gem install mg`"
20
5
  end
21
6
 
7
+ MG.new("jabbot.gemspec")
8
+
22
9
  require 'rake/testtask'
23
10
  Rake::TestTask.new(:test) do |test|
24
11
  test.libs << 'lib' << 'test'
@@ -27,19 +14,3 @@ Rake::TestTask.new(:test) do |test|
27
14
  end
28
15
 
29
16
  task :default => :test
30
-
31
- require 'rake/rdoctask'
32
- Rake::RDocTask.new do |rdoc|
33
- if File.exist?('VERSION.yml')
34
- config = YAML.load(File.read('VERSION.yml'))
35
- version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
36
- else
37
- version = ""
38
- end
39
-
40
- rdoc.rdoc_dir = 'rdoc'
41
- rdoc.title = "jabbot #{version}"
42
- rdoc.rdoc_files.include('README*')
43
- rdoc.rdoc_files.include('lib/**/*.rb')
44
- end
45
-
@@ -6,47 +6,14 @@ require 'xmpp4r/version/helper/simpleresponder'
6
6
  require 'yaml'
7
7
  require File.join(File.dirname(__FILE__), 'hash')
8
8
 
9
- module Jabbot
10
-
11
- # :stopdoc:
12
- VERSION = '0.1.2'
13
- LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
14
- PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
15
- # :startdoc:
16
-
17
- # Returns the version string for the library.
18
- #
19
- def self.version
20
- VERSION
21
- end
22
-
23
- # Returns the library path for the module. If any arguments are given,
24
- # they will be joined to the end of the libray path using
25
- # <tt>File.join</tt>.
26
- #
27
- def self.libpath( *args )
28
- args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
29
- end
30
-
31
- # Returns the lpath for the module. If any arguments are given,
32
- # they will be joined to the end of the path using
33
- # <tt>File.join</tt>.
34
- #
35
- def self.path( *args )
36
- args.empty? ? PATH : ::File.join(PATH, args.flatten)
37
- end
38
-
39
- # Utility method used to require all files ending in .rb that lie in the
40
- # directory below this file that has the same name as the filename passed
41
- # in. Optionally, a specific _directory_ name can be passed in such that
42
- # the _filename_ does not have to be equivalent to the directory.
43
- #
44
- def self.require_all_libs_relative_to( fname, dir = nil )
45
- dir ||= File.basename(fname, '.*')
46
- search_me = File.expand_path(File.join(File.dirname(fname), dir, '**', '*.rb'))
47
- Dir.glob(search_me).sort.each {|rb| require rb }
48
- end
9
+ require 'jabbot/bot.rb'
10
+ require 'jabbot/config.rb'
11
+ require 'jabbot/handlers.rb'
12
+ require 'jabbot/macros.rb'
13
+ require 'jabbot/message.rb'
14
+ require 'jabbot/version.rb'
49
15
 
16
+ module Jabbot
50
17
  @@app_file = lambda do
51
18
  ignore = [
52
19
  /lib\/twibot.*\.rb/, # Library
@@ -79,6 +46,5 @@ module Jabbot
79
46
  end # module Jabbot
80
47
 
81
48
  Thread.abort_on_exception = true
82
- Jabbot.require_all_libs_relative_to(__FILE__)
83
49
 
84
50
  # EOF
@@ -9,7 +9,7 @@ module Jabbot
9
9
  class Bot
10
10
  include Jabbot::Handlers
11
11
  attr_reader :client
12
- attr_reader :user
12
+ attr_reader :users
13
13
 
14
14
  Message = Struct.new(:user, :text, :time) do
15
15
  def to_s
@@ -22,16 +22,26 @@ module Jabbot
22
22
  @config = options || Jabbot::Config.default << Jabbot::FileConfig.new
23
23
  @log = nil
24
24
  @abort = false
25
- @user = []
25
+ @users = []
26
26
 
27
27
  rescue Exception => krash
28
28
  raise SystemExit.new(krash.message)
29
29
  end
30
30
 
31
+ # Enable debugging mode.
32
+ # All xmpp4r-internal calls to Jabber::Debuglog are
33
+ # printed to $stderr by default.
34
+ # You may change the logger by using
35
+ # Jabber::Logger = Logger.new(…)
36
+ def debug!
37
+ Jabber::debug = true
38
+ end
39
+
31
40
  #
32
41
  # connect to Jabber and join channel
33
42
  #
34
43
  def connect
44
+ #Jabber::debug = true
35
45
  @jid = Jabber::JID.new(login)
36
46
  @mucjid = Jabber::JID.new("#{channel}@#{server}")
37
47
 
@@ -46,7 +56,7 @@ module Jabbot
46
56
  else
47
57
  @jid.resource = config[:resource] || "jabbot"
48
58
  @mucjid.resource = config[:nick] || "jabbot"
49
- @user << config[:nick]
59
+ @users << config[:nick]
50
60
  end
51
61
 
52
62
  @client = Jabber::Client.new(@jid)
@@ -74,6 +84,7 @@ module Jabbot
74
84
  exit
75
85
  end
76
86
 
87
+ debug! if config[:debug]
77
88
  connect
78
89
  poll
79
90
  end
@@ -143,8 +154,8 @@ module Jabbot
143
154
  end
144
155
 
145
156
  muc.on_join do |time, nick|
146
- unless @user.include? nick
147
- @user << nick
157
+ unless @users.include? nick
158
+ @users << nick
148
159
  end
149
160
  if time.nil?
150
161
  begin
@@ -155,9 +166,9 @@ module Jabbot
155
166
  end
156
167
  end
157
168
  end
158
-
169
+
159
170
  muc.on_leave do |time, nick|
160
- @user.delete(nick)
171
+ @users.delete(nick)
161
172
  if time.nil?
162
173
  begin
163
174
  dispatch_messages(:leave, [Message.new(nick, "leave", Time.now)])
@@ -167,7 +178,7 @@ module Jabbot
167
178
  end
168
179
  end
169
180
  end
170
-
181
+
171
182
  muc.on_subject do |time, nick, subject|
172
183
  if time.nil?
173
184
  begin
@@ -213,7 +224,6 @@ module Jabbot
213
224
  @conf = nil
214
225
  end
215
226
 
216
- private
217
227
  #
218
228
  # Map configuration settings
219
229
  #
@@ -27,7 +27,8 @@ module Jabbot
27
27
  :nick => 'jabbot',
28
28
  :channel => nil,
29
29
  :server => nil,
30
- :resource => nil
30
+ :resource => nil,
31
+ :debug => false
31
32
  }
32
33
 
33
34
  def initialize(settings = {})
@@ -1,54 +1,105 @@
1
1
  module Jabbot
2
- @@prompt = false
3
-
4
- def self.prompt=(p)
5
- @@prompt = f
6
- end
7
-
2
+ # Defines the DSL used for bots.
8
3
  module Macros
9
4
  def self.included(mod)
10
5
  @@bot = nil
11
6
  end
12
7
 
8
+ # Configure the bot
9
+ # The block gets passed an instance of OpenStruct used as the config
10
+ # See lib/jabbot/config.rb for possible options
13
11
  def configure(&blk)
14
12
  bot.configure(&blk)
15
13
  end
16
14
 
15
+ # Returns the current config hash
16
+ def config
17
+ bot.config
18
+ end
19
+
20
+ # Add message handler
21
+ # pattern - can be a String containing :matches
22
+ # or a Regexp with matching groups
23
+ # options - Hash defining users to receive messages from
24
+ # { :from => ['user1', 'user2', ...] }
25
+ # blk - The block to execute on successfull match
17
26
  def message(pattern = nil, options = {}, &blk)
18
27
  add_handler(:message, pattern, options, &blk)
19
28
  end
20
29
 
30
+ # Add query handler
31
+ # Only private messages are matched against this handler
32
+ #
33
+ # pattern - can be a String containing :matches
34
+ # or a Regexp with matching groups
35
+ # options - Hash defining users to receive messages from
36
+ # { :from => ['user1', 'user2', ...] }
37
+ # blk - The block to execute on successfull match
21
38
  def query(pattern = nil, options = {}, &blk)
22
39
  add_handler(:private, pattern, options, &blk)
23
40
  end
24
41
  alias_method :private_message, :query
25
42
 
43
+ # Add join handler
44
+ # Block gets executed when new user joins
45
+ #
46
+ # options - Hash defining users to react on joins
47
+ # { :from => ['user1', 'user2', ...] }
48
+ # blk - The block to execute on successfull match
26
49
  def join(options = {}, &blk)
27
50
  add_handler(:join, /\Ajoin\Z/, options, &blk)
28
51
  end
29
-
52
+
53
+ # Add leave handler
54
+ # Block gets executed when user leaves the channel
55
+ #
56
+ # options - Hash defining users to react on leaves
57
+ # { :from => ['user1', 'user2', ...] }
58
+ # blk - The block to execute on successfull match
30
59
  def leave(options = {}, &blk)
31
60
  add_handler(:leave, /\Aleave\Z/, options, &blk)
32
61
  end
33
62
 
63
+ # Add subject/topic handler
64
+ # Block gets executed when topic gets changed
65
+ #
66
+ # pattern - can be a String containing :matches
67
+ # or a Regexp with matching groups
68
+ # options - Hash defining users
69
+ # { :from => ['user1', 'user2', ...] }
70
+ # blk - The block to execute on successfull match
34
71
  def subject(pattern = nil, options = {}, &blk)
35
72
  add_handler(:subject, pattern, options, &blk)
36
73
  end
37
74
  alias_method :topic, :subject
38
75
 
76
+ # Returns the Jabber::Client instance used
77
+ # You may execute low-level functions on this object if needed
39
78
  def client
40
79
  bot.client
41
80
  end
42
81
 
82
+ # Close the connection and exit the bot
43
83
  def close
44
84
  bot.close
45
85
  end
46
86
  alias_method :quit, :close
47
87
 
48
- def user
49
- bot.user
88
+ # Get array of all users in the channel
89
+ def users
90
+ bot.users
50
91
  end
51
92
 
93
+ # Post message back to the channel
94
+ # msg - Message to send, can be a String to be send
95
+ # or a Hash: { msg => user }
96
+ # to - User to send the message to,
97
+ # left blank if syntax-sugar variant is used
98
+ #
99
+ # Syntax-sugar variant:
100
+ # post "msg" => "user1"
101
+ # is the same as
102
+ # post "msg", "user1"
52
103
  def post(msg, to=nil)
53
104
  if msg.is_a?(Hash) && msg.keys.size == 1
54
105
  to = msg.values.first
@@ -57,15 +108,19 @@ module Jabbot
57
108
  bot.send_message(msg, to)
58
109
  end
59
110
 
111
+ # Returns boolean wether to start the bot at_exit
60
112
  def run?
61
113
  !@@bot.nil?
62
114
  end
63
115
 
64
- private
116
+ private
117
+
118
+ # Low-level method to add new Handler to the bot
65
119
  def add_handler(type, pattern, options, &blk)
66
120
  bot.add_handler(type, Jabbot::Handler.new(pattern, options, &blk))
67
121
  end
68
122
 
123
+ # Low-level method to create new instance of a bot
69
124
  def bot
70
125
  return @@bot unless @@bot.nil?
71
126