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 +21 -0
- data/README.md +157 -0
- data/Rakefile +4 -33
- data/lib/jabbot.rb +7 -41
- data/lib/jabbot/bot.rb +19 -9
- data/lib/jabbot/config.rb +2 -1
- data/lib/jabbot/macros.rb +65 -10
- data/lib/jabbot/version.rb +3 -0
- data/test/helper.rb +64 -0
- data/test/test_bot.rb +11 -41
- data/test/test_config.rb +17 -17
- data/test/test_handler.rb +76 -78
- data/test/test_hash.rb +5 -5
- data/test/test_macros.rb +31 -0
- metadata +48 -42
- data/README.rdoc +0 -141
- data/VERSION.yml +0 -4
- data/test/test_helper.rb +0 -38
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.
|
data/README.md
ADDED
@@ -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 '
|
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
|
-
|
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
|
-
|
data/lib/jabbot.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
data/lib/jabbot/bot.rb
CHANGED
@@ -9,7 +9,7 @@ module Jabbot
|
|
9
9
|
class Bot
|
10
10
|
include Jabbot::Handlers
|
11
11
|
attr_reader :client
|
12
|
-
attr_reader :
|
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
|
-
@
|
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
|
-
@
|
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 @
|
147
|
-
@
|
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
|
-
@
|
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
|
#
|
data/lib/jabbot/config.rb
CHANGED
data/lib/jabbot/macros.rb
CHANGED
@@ -1,54 +1,105 @@
|
|
1
1
|
module Jabbot
|
2
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
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
|
|