botfly 0.1.1 → 0.2.1
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/README.rdoc +13 -3
- data/VERSION +1 -1
- data/botfly.gemspec +12 -4
- data/example.rb +30 -15
- data/lib/botfly.rb +8 -3
- data/lib/botfly/bot.rb +16 -28
- data/lib/botfly/common_block_acceptor.rb +51 -0
- data/lib/botfly/matcher.rb +5 -1
- data/lib/botfly/matcher/body_matcher.rb +2 -2
- data/lib/botfly/matcher/matcher.rb +1 -1
- data/lib/botfly/matcher/muc_nick_matcher.rb +13 -0
- data/lib/botfly/matcher/muc_text_matcher.rb +13 -0
- data/lib/botfly/matcher/muc_time_matcher.rb +14 -0
- data/lib/botfly/matcher/nick_matcher.rb +3 -2
- data/lib/botfly/matcher/subject_matcher.rb +2 -2
- data/lib/botfly/muc_client.rb +70 -0
- data/lib/botfly/responder.rb +4 -1
- data/lib/botfly/responder/common_responder_methods.rb +20 -0
- data/lib/botfly/responder/message_responder.rb +2 -3
- data/lib/botfly/responder/muc_message_responder.rb +4 -0
- data/lib/botfly/responder/muc_responder.rb +68 -0
- data/lib/botfly/responder/presence_responder.rb +18 -0
- data/lib/botfly/responder/responder.rb +11 -10
- data/retrobot.rb +44 -0
- metadata +12 -4
- data/.document +0 -5
data/README.rdoc
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
-
=
|
1
|
+
= Botfly
|
2
2
|
|
3
|
-
|
3
|
+
Botfly is a Jabber Bot DSL that makes writing bots a joy.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install botfly
|
8
|
+
|
9
|
+
Go nuts!
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
Coming soon, for now take a look at `example.rb`
|
4
14
|
|
5
15
|
== Note on Patches/Pull Requests
|
6
|
-
|
16
|
+
|
7
17
|
* Fork the project.
|
8
18
|
* Make your feature addition or bug fix.
|
9
19
|
* Add tests for it. This is important so I don't break it in a
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.1
|
data/botfly.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{botfly}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ryan Neufeld"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-17}
|
13
13
|
s.description = %q{Botfly is a Jabber Bot DSL that lets you write bots with ease. Enjoy, while it's still fresh and VERY ALPHA.}
|
14
14
|
s.email = %q{ryan@ryanneufeld.ca}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -17,8 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
-
".
|
21
|
-
".gitignore",
|
20
|
+
".gitignore",
|
22
21
|
"LICENSE",
|
23
22
|
"README.rdoc",
|
24
23
|
"Rakefile",
|
@@ -27,15 +26,24 @@ Gem::Specification.new do |s|
|
|
27
26
|
"example.rb",
|
28
27
|
"lib/botfly.rb",
|
29
28
|
"lib/botfly/bot.rb",
|
29
|
+
"lib/botfly/common_block_acceptor.rb",
|
30
30
|
"lib/botfly/matcher.rb",
|
31
31
|
"lib/botfly/matcher/body_matcher.rb",
|
32
32
|
"lib/botfly/matcher/matcher.rb",
|
33
|
+
"lib/botfly/matcher/muc_nick_matcher.rb",
|
34
|
+
"lib/botfly/matcher/muc_text_matcher.rb",
|
35
|
+
"lib/botfly/matcher/muc_time_matcher.rb",
|
33
36
|
"lib/botfly/matcher/nick_matcher.rb",
|
34
37
|
"lib/botfly/matcher/subject_matcher.rb",
|
38
|
+
"lib/botfly/muc_client.rb",
|
35
39
|
"lib/botfly/responder.rb",
|
40
|
+
"lib/botfly/responder/common_responder_methods.rb",
|
36
41
|
"lib/botfly/responder/message_responder.rb",
|
42
|
+
"lib/botfly/responder/muc_message_responder.rb",
|
43
|
+
"lib/botfly/responder/muc_responder.rb",
|
37
44
|
"lib/botfly/responder/presence_responder.rb",
|
38
45
|
"lib/botfly/responder/responder.rb",
|
46
|
+
"retrobot.rb",
|
39
47
|
"spec/botfly_spec.rb",
|
40
48
|
"spec/spec.opts",
|
41
49
|
"spec/spec_helper.rb"
|
data/example.rb
CHANGED
@@ -1,24 +1,39 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'botfly'
|
3
|
-
|
3
|
+
require 'fileutils'
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
config = YAML::load(ARGF.read) if ARGF
|
7
|
-
puts config.inspect
|
8
|
-
|
9
|
-
Jabber::debug = false
|
10
7
|
|
11
8
|
bot = Botfly.login(config["jid"],config["pass"]) do
|
12
|
-
on
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
blame_responder = on.message.body(/^blame/) do |a|
|
10
|
+
match = @body.match(/^blame (.*):(.*)$/)
|
11
|
+
file = match[1]
|
12
|
+
line = match[2].to_i
|
13
|
+
|
14
|
+
project = "/Users/burke/src/jsgithistory"
|
15
|
+
|
16
|
+
result=nil
|
17
|
+
FileUtils.cd(project) do
|
18
|
+
result = `git blame -p -L#{line},#{line} #{file}`
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
author = result.scan(/author (.*)\n/).first
|
22
|
+
time = Time.at(result.scan(/author-time (.*)\n/).first.to_i)
|
23
|
+
commit = result.lines.first.split(' ').first.strip
|
24
|
+
|
25
|
+
reply "#{author}, #{time}, #{commit}"
|
26
|
+
end
|
27
|
+
join('bots') do
|
28
|
+
on.message do
|
29
|
+
reply "Hi"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
on.message.from(/^rkneufeld/).body(/^kb$/) do
|
33
|
+
reply "Sure thing! You ARE the boss!"
|
34
|
+
remove blame_responder
|
35
|
+
reply "There, all done"
|
36
|
+
end
|
22
37
|
end
|
23
|
-
|
24
|
-
loop
|
38
|
+
|
39
|
+
Thread.stop;loop
|
data/lib/botfly.rb
CHANGED
@@ -2,12 +2,16 @@ require 'rubygems'
|
|
2
2
|
|
3
3
|
require 'xmpp4r'
|
4
4
|
require 'xmpp4r/muc'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'logger'
|
5
7
|
|
8
|
+
require 'botfly/common_block_acceptor'
|
6
9
|
require 'botfly/responder'
|
7
10
|
require 'botfly/bot'
|
8
11
|
require 'botfly/matcher'
|
12
|
+
require 'botfly/muc_client'
|
9
13
|
|
10
|
-
|
14
|
+
Thread.abort_on_exception = true
|
11
15
|
|
12
16
|
module Botfly
|
13
17
|
def Botfly.logger
|
@@ -18,7 +22,8 @@ module Botfly
|
|
18
22
|
@logfile = logfile
|
19
23
|
Botfly.logger.info("BOTFLY: #login")
|
20
24
|
bot = Botfly::Bot.new(jid,pass)
|
21
|
-
bot.
|
25
|
+
bot.connect
|
26
|
+
bot.instance_exec(&block)
|
22
27
|
return bot # At this point doesn't get returned, as the thread is stopped
|
23
28
|
end
|
24
|
-
end
|
29
|
+
end
|
data/lib/botfly/bot.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
module Botfly
|
4
|
-
class Bot
|
5
|
-
attr_reader :
|
4
|
+
class Bot < CommonBlockAcceptor
|
5
|
+
attr_reader :jid
|
6
|
+
|
6
7
|
def initialize(jid,pass)
|
8
|
+
super
|
7
9
|
Botfly.logger.info(" BOT: Bot#new")
|
8
10
|
@password = pass
|
9
11
|
@jid = Jabber::JID.new(jid)
|
10
12
|
@client = Jabber::Client.new(@jid)
|
11
|
-
@responders = {}
|
12
13
|
@main_thread = Thread.current
|
13
14
|
end
|
14
15
|
|
@@ -17,27 +18,27 @@ module Botfly
|
|
17
18
|
@client.connect
|
18
19
|
@client.auth(@password)
|
19
20
|
Botfly.logger.info(" BOT: Connected")
|
20
|
-
|
21
|
+
register_for_callbacks
|
21
22
|
@client.send(Jabber::Presence.new.set_status("Carrier has arrived"))
|
22
23
|
#Thread.stop
|
23
24
|
end
|
24
25
|
|
25
|
-
def
|
26
|
-
Botfly.
|
27
|
-
klass = Botfly.const_get(type.to_s.capitalize + "Responder")
|
28
|
-
(@responders[type] ||= []) << responder = klass.new(@client, self, &block)
|
29
|
-
Botfly.logger.info(" BOT: #{type.to_s.capitalize}Responder added to responder chain")
|
30
|
-
return responder
|
26
|
+
def join(room_name,&block)
|
27
|
+
return Botfly::MUCClient.new(room_name,self,&block)
|
31
28
|
end
|
32
29
|
|
33
30
|
def quit
|
34
31
|
@client.close
|
35
32
|
@main_thread.continue
|
36
33
|
end
|
37
|
-
|
34
|
+
|
35
|
+
def to_debug_s
|
36
|
+
"BOT"
|
37
|
+
end
|
38
|
+
|
38
39
|
private
|
39
40
|
|
40
|
-
def
|
41
|
+
def register_for_callbacks
|
41
42
|
Botfly.logger.info(" BOT: Registering for callbacks with client")
|
42
43
|
# @client.add_update_callback {|presence| respond_to(:update, :presence => presence) }
|
43
44
|
# @client.add_subscription_request_callback {|item, pres| } # requires Roster helper
|
@@ -45,7 +46,7 @@ module Botfly
|
|
45
46
|
Botfly.logger.debug(" CB: Got Message")
|
46
47
|
respond_to(:message, :message => message)
|
47
48
|
end
|
48
|
-
@client.add_presence_callback do |old_presence
|
49
|
+
@client.add_presence_callback do |new_presence,old_presence|
|
49
50
|
Botfly.logger.debug(" CB: Got Presence")
|
50
51
|
respond_to(:presence, :old => old_presence, :new => new_presence)
|
51
52
|
end
|
@@ -54,20 +55,7 @@ module Botfly
|
|
54
55
|
|
55
56
|
def respond_to(callback_type, params)
|
56
57
|
Botfly.logger.info(" BOT: Responding to callback of type: #{callback_type}")
|
57
|
-
responders
|
58
|
-
responders[callback_type].each {|r| r.callback_with params} if responders[callback_type]
|
58
|
+
@responders[callback_type].each {|r| r.callback_with params} if @responders[callback_type]
|
59
59
|
end
|
60
|
-
|
61
|
-
# def register_for_muc_callbacks(client)
|
62
|
-
# params = {:muc => client}
|
63
|
-
## client.on_join {|time,nick| respond_to(:join, params.merge!(:time=>time,:nick=>nick))}
|
64
|
-
# client.on_leave {|time,nick| respond_to(:leave, params.merge!(:time=>time,:nick=>nick))}
|
65
|
-
# client.on_message {|time,nick,text| respond_to(:message, params.merge!(:time=>time,:nick=>nick,:text=>text))}
|
66
|
-
# client.on_private_message {|time,nick,text| respond_to(:private_message, params.merge!(:time=>time,:nick=>nick,:text=>text))}
|
67
|
-
# client.on_room_message {|time,text| respond_to(:room_message, params.merge!(:time => time, :text => text))}
|
68
|
-
# client.on_self_leave {|time| respond_to(:self_leave, params.merge!(:time => time)) }
|
69
|
-
# client.on_subject {|time,nick,subject| respond_to(:subject, params.merge!(:time => time, :nick => nickname, :subject => subject))}
|
70
|
-
# end
|
71
|
-
|
72
60
|
end
|
73
|
-
end
|
61
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Botfly
|
2
|
+
class CommonBlockAcceptor
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
attr_accessor :responders
|
6
|
+
attr_reader :client
|
7
|
+
|
8
|
+
def initialize(ignored,ignore)
|
9
|
+
@block_state = {}
|
10
|
+
@responders = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
ABSTRACT_RAISE_ERROR = "AbstractMethodError: Implement in subclass"
|
14
|
+
def to_debug_s; raise ABSTRACT_RAISE_ERROR; end
|
15
|
+
def respond_to(type,params); raise ABSTRACT_RAISE_ERROR; end
|
16
|
+
def on; raise ABSTRACT_RAISE_ERROR; end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
@block_state[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(key, set_to)
|
23
|
+
@block_state[key] = set_to
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove_responder(id_to_remove)
|
27
|
+
Botfly.logger.info("BOT: Removing responder #{id_to_remove}")
|
28
|
+
@responders.each { |pair| key,chain = pair; chain.reject! {|r| r.id == id_to_remove } }
|
29
|
+
end
|
30
|
+
|
31
|
+
def on
|
32
|
+
return OnRecognizer.new(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
class OnRecognizer
|
36
|
+
def initialize(obj); @obj = obj; end
|
37
|
+
|
38
|
+
def method_missing(type,&block)
|
39
|
+
Botfly.logger.info("#{@obj.to_debug_s}: Bot#on")
|
40
|
+
klass = Botfly.const_get(@obj.class_prefix + type.to_s.capitalize + "Responder")
|
41
|
+
(@obj.responders[type] ||= []) << responder = klass.new(@obj, &block)
|
42
|
+
Botfly.logger.info("#{@obj.to_debug_s}: #{@obj.class_prefix}#{type.to_s.capitalize}Responder added to responder chain")
|
43
|
+
return responder
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def class_prefix
|
48
|
+
''
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/botfly/matcher.rb
CHANGED
@@ -2,4 +2,8 @@ require 'botfly/matcher/matcher'
|
|
2
2
|
# TODO: Scope the matchers by responder
|
3
3
|
require 'botfly/matcher/nick_matcher'
|
4
4
|
require 'botfly/matcher/body_matcher'
|
5
|
-
require 'botfly/matcher/subject_matcher'
|
5
|
+
require 'botfly/matcher/subject_matcher'
|
6
|
+
|
7
|
+
require 'botfly/matcher/muc_nick_matcher'
|
8
|
+
require 'botfly/matcher/muc_text_matcher'
|
9
|
+
require 'botfly/matcher/muc_time_matcher'
|
@@ -5,8 +5,8 @@ module Botfly
|
|
5
5
|
class BodyMatcher < Matcher
|
6
6
|
def match(params)
|
7
7
|
msg = params[:message]
|
8
|
-
Botfly.logger.debug "
|
9
|
-
Botfly.logger.debug "
|
8
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{msg.body.inspect}"
|
9
|
+
Botfly.logger.debug "RESULT: #{(msg.body =~ @condition).inspect}"
|
10
10
|
return msg.body =~ @condition
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'botfly/matcher'
|
2
|
+
|
3
|
+
module Botfly
|
4
|
+
class MUCNickMatcher < Matcher
|
5
|
+
def match(params)
|
6
|
+
nick = params[:nick]
|
7
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{nick}"
|
8
|
+
Botfly.logger.debug "RESULT: #{(nick =~ @condition).inspect}"
|
9
|
+
return nick =~ @condition
|
10
|
+
end
|
11
|
+
end
|
12
|
+
MUCFromMatcher = MUCNickMatcher
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'botfly/matcher'
|
2
|
+
|
3
|
+
module Botfly
|
4
|
+
class MUCTextMatcher < Matcher
|
5
|
+
def match(params)
|
6
|
+
text = params[:text]
|
7
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{text}"
|
8
|
+
Botfly.logger.debug "RESULT: #{(text =~ @condition).inspect}"
|
9
|
+
return text =~ @condition
|
10
|
+
end
|
11
|
+
end
|
12
|
+
MUCBodyMatcher = MUCTextMatcher
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'botfly/matcher'
|
2
|
+
|
3
|
+
# FIXME: Make time matching much more robust
|
4
|
+
module Botfly
|
5
|
+
class MUCTimeMatcher < Matcher
|
6
|
+
def match(params)
|
7
|
+
time = params[:time]
|
8
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{time}"
|
9
|
+
Botfly.logger.debug "RESULT: #{(time =~ @condition).inspect}"
|
10
|
+
return time =~ @condition
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -5,9 +5,10 @@ module Botfly
|
|
5
5
|
class NickMatcher < Matcher
|
6
6
|
def match(params)
|
7
7
|
msg = params[:message]
|
8
|
-
Botfly.logger.debug "
|
9
|
-
Botfly.logger.debug "
|
8
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{msg.from.inspect}"
|
9
|
+
Botfly.logger.debug "RESULT: #{(msg.from.node =~ @condition).inspect}"
|
10
10
|
return msg.from.node =~ @condition
|
11
11
|
end
|
12
12
|
end
|
13
|
+
FromMatcher = NickMatcher
|
13
14
|
end
|
@@ -5,8 +5,8 @@ module Botfly
|
|
5
5
|
class SubjectMatcher < Matcher
|
6
6
|
def match(params)
|
7
7
|
msg = params[:message]
|
8
|
-
Botfly.logger.debug "
|
9
|
-
Botfly.logger.debug "
|
8
|
+
Botfly.logger.debug "MCH: Matching #{@condition.inspect} against #{msg.subject.inspect}"
|
9
|
+
Botfly.logger.debug "RESULT: #{(msg.subject =~ @condition).inspect}"
|
10
10
|
return msg.subject.node =~ @condition
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'xmpp4r/muc'
|
2
|
+
|
3
|
+
module Botfly
|
4
|
+
class MUCClient < CommonBlockAcceptor
|
5
|
+
attr_reader :bot, :muc
|
6
|
+
|
7
|
+
def room; self; end
|
8
|
+
|
9
|
+
def initialize(room, bot, &block)
|
10
|
+
super
|
11
|
+
Botfly.logger.info("MUC: New client created")
|
12
|
+
@bot = bot
|
13
|
+
@client = @bot.client
|
14
|
+
@room = room
|
15
|
+
@domain = "conference.#{@bot.jid.domain}" # A sensible default for now
|
16
|
+
@resource = @bot.jid.resource
|
17
|
+
|
18
|
+
execute(&block) if block_given? # i.e. join(room) do ... end
|
19
|
+
return self
|
20
|
+
end
|
21
|
+
|
22
|
+
def as(resource, &block)
|
23
|
+
Botfly.logger.info("MUC: as #{resource}")
|
24
|
+
@resource = resource
|
25
|
+
execute(&block) if block_given?
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
|
29
|
+
def leave_room; raise "Implement Me!"; end
|
30
|
+
|
31
|
+
|
32
|
+
def respond_to(callback_type, params)
|
33
|
+
Botfly.logger.info("MUC: Got callback with time #{params[:time].inspect}")
|
34
|
+
if !params[:time].nil? # Only respond to messages from the server, if time is nil server didn't send
|
35
|
+
Botfly.logger.info("MUC: Responding to callback of type: #{callback_type} with time of #{params[:time]}")
|
36
|
+
@responders[callback_type].each {|r| r.callback_with params} if @responders[callback_type]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_debug_s; "MUC"; end
|
41
|
+
def class_prefix; "MUC"; end
|
42
|
+
private
|
43
|
+
|
44
|
+
def connect
|
45
|
+
Botfly.logger.info("MUC: Connecting...")
|
46
|
+
@muc = Jabber::MUC::SimpleMUCClient.new(@bot.client)
|
47
|
+
register_for_callbacks
|
48
|
+
@jid = Jabber::JID.new("#{@room}@#{@domain}/#{@resource}")
|
49
|
+
@muc.join(@jid)
|
50
|
+
Botfly.logger.info("MUC: Done connecting")
|
51
|
+
end
|
52
|
+
|
53
|
+
def execute(&block)
|
54
|
+
Botfly.logger.info("MUC: Block deteceted, executing...")
|
55
|
+
connect
|
56
|
+
instance_eval(&block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def register_for_callbacks
|
60
|
+
Botfly.logger.info("MUC: Registering for MUC callbacks")
|
61
|
+
@muc.on_join {|time,nick| respond_to(:join, :time=>time,:nick=>nick)}
|
62
|
+
@muc.on_leave {|time,nick| respond_to(:leave, :time=>time,:nick=>nick)}
|
63
|
+
@muc.on_message {|time,nick,text| respond_to(:message, :time=>time,:nick=>nick,:text=>text)}
|
64
|
+
#@muc.on_private_message {|time,nick,text| respond_to(:private_message, :time=>time,:nick=>nick,:text=>text)} # Low on the priority to impl. list
|
65
|
+
@muc.on_room_message {|time,text| respond_to(:room_message, :time => time, :text => text)}
|
66
|
+
@muc.on_self_leave {|time| respond_to(:self_leave, :time => time) }
|
67
|
+
@muc.on_subject {|time,nick,subject| respond_to(:subject, :time => time, :nick => nickname, :subject => subject)}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/botfly/responder.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'botfly/responder/common_responder_methods'
|
1
2
|
require 'botfly/responder/responder'
|
2
3
|
require 'botfly/responder/message_responder'
|
3
|
-
require 'botfly/responder/presence_responder'
|
4
|
+
require 'botfly/responder/presence_responder'
|
5
|
+
require 'botfly/responder/muc_responder'
|
6
|
+
require 'botfly/responder/muc_message_responder'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Botfly
|
2
|
+
module CommonResponderMethods
|
3
|
+
def send(nick, message, opts = {})
|
4
|
+
Botfly.logger.debug("RSP: Sending message")
|
5
|
+
|
6
|
+
# Fix the nickname if no domain/resource was given by adding your domain
|
7
|
+
nick += "@" + @bot.jid.domain if nick !~ /@.*/
|
8
|
+
|
9
|
+
opts = { :type => :chat }.merge(opts)
|
10
|
+
msg = Jabber::Message.new(nick, message)
|
11
|
+
msg.type = opts[:type]
|
12
|
+
msg.subject = opts[:subject]
|
13
|
+
@client.send(msg)
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove(responder_id)
|
17
|
+
@bot.remove_responder(responder_id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'forwardable'
|
2
1
|
module Botfly
|
3
2
|
class MessageResponder < Responder
|
4
3
|
extend Forwardable
|
5
4
|
def setup_instance_variables(params)
|
6
|
-
Botfly.logger.debug("
|
5
|
+
Botfly.logger.debug("RSP: MessageResponder setting up instance variables")
|
7
6
|
@message = params[:message]
|
8
7
|
@body = @message.body
|
9
8
|
@chat_state = @message.chat_state
|
@@ -14,7 +13,7 @@ module Botfly
|
|
14
13
|
end
|
15
14
|
|
16
15
|
def reply(text)
|
17
|
-
Botfly.logger.debug("
|
16
|
+
Botfly.logger.debug("RSP: MessageResponder#reply called")
|
18
17
|
msg = Jabber::Message.new(@from, text)
|
19
18
|
msg.type = :chat
|
20
19
|
@client.send(msg)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# FIXME: DRY up this and Respnoder
|
2
|
+
module Botfly
|
3
|
+
class MUCResponder < Responder
|
4
|
+
@@id = 1
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegator :@muc, :on
|
8
|
+
def_delegator :@bot, :client
|
9
|
+
def_delegator :@muc, :room
|
10
|
+
|
11
|
+
def initialize(muc,&block)
|
12
|
+
Botfly.logger.info("RSP: #{self.class.to_s}#new")
|
13
|
+
@matcher_chain = []
|
14
|
+
@muc = muc
|
15
|
+
@bot = @muc.bot
|
16
|
+
|
17
|
+
@callback = block if block_given?
|
18
|
+
@id = @@id += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method,condition,&block)
|
22
|
+
Botfly.logger.info("RSP: Responder##{method}(#{condition.inspect})")
|
23
|
+
|
24
|
+
add_matcher(method,condition)
|
25
|
+
|
26
|
+
if block_given?
|
27
|
+
Botfly.logger.info("RSP: Callback recorded: #{block.inspect}")
|
28
|
+
@callback = block
|
29
|
+
return @id
|
30
|
+
end
|
31
|
+
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
def callback_with(params)
|
36
|
+
Botfly.logger.debug("RSP: Launching callback with params: #{params.inspect}")
|
37
|
+
|
38
|
+
setup_instance_variables(params)
|
39
|
+
if @matcher_chain.all? {|matcher| matcher.match(params) }
|
40
|
+
Botfly.logger.debug("RSP: All matchers passed")
|
41
|
+
cb = @callback # Ruby makes it difficult to apply & to an instance variable
|
42
|
+
instance_eval &cb
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def leave #room
|
47
|
+
raise "NotImplementedError: Sorry, coming soon!"
|
48
|
+
end
|
49
|
+
|
50
|
+
def say(msg)
|
51
|
+
@muc.muc.say(msg)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def add_matcher(method, condition)
|
56
|
+
klass = Botfly.const_get("MUC" + method.to_s.capitalize + "Matcher")
|
57
|
+
@matcher_chain << klass.new(condition)
|
58
|
+
|
59
|
+
Botfly.logger.debug("RSP: Adding to matcher chain: #{@matcher_chain.inspect}")
|
60
|
+
end
|
61
|
+
|
62
|
+
def setup_instance_variables(params)
|
63
|
+
@text = @body = params[:text]
|
64
|
+
@nick = @from = params[:nick]
|
65
|
+
@time = params[:time]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -2,6 +2,24 @@ module Botfly
|
|
2
2
|
class PresenceResponder < Responder
|
3
3
|
def setup_instance_variables(params)
|
4
4
|
Botfly.logger.debug(" RSP: #{self.class} setting up instance variables")
|
5
|
+
|
6
|
+
# TODO: Figure out how xmpp works with presence messages so I know what to expect
|
7
|
+
if params[:new]
|
8
|
+
@presence = params[:new]
|
9
|
+
@from = @presence.from
|
10
|
+
@show = @presence.show
|
11
|
+
@priority = @presence.priority
|
12
|
+
@status = @presence.status
|
13
|
+
@type = @presence.type
|
14
|
+
end
|
15
|
+
|
16
|
+
if params[:old]
|
17
|
+
@old_presence = params[:old]
|
18
|
+
@old_status = @old_presence.status
|
19
|
+
@old_priority = @old_presence.priority
|
20
|
+
@old_type = @old_presence.type
|
21
|
+
@old_show = @old_presence.show
|
22
|
+
end
|
5
23
|
end
|
6
24
|
end
|
7
25
|
end
|
@@ -1,13 +1,18 @@
|
|
1
1
|
module Botfly
|
2
2
|
class Responder
|
3
|
-
|
3
|
+
@@id = 1
|
4
|
+
include Botfly::CommonResponderMethods
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :callback, :callback_type, :id, :bot
|
8
|
+
def_delegator :@bot, :client
|
4
9
|
|
5
|
-
def initialize(
|
10
|
+
def initialize(bot,&block)
|
6
11
|
Botfly.logger.info(" RSP: #{self.class.to_s}#new")
|
7
12
|
@matcher_chain = []
|
8
13
|
@bot = bot
|
9
|
-
@client = client
|
10
14
|
@callback = block if block_given?
|
15
|
+
@id = @@id += 1
|
11
16
|
end
|
12
17
|
|
13
18
|
def method_missing(method,condition,&block)
|
@@ -17,7 +22,8 @@ module Botfly
|
|
17
22
|
|
18
23
|
if block_given?
|
19
24
|
Botfly.logger.info(" RSP: Callback recorded: #{block.inspect}")
|
20
|
-
@callback = block
|
25
|
+
@callback = block
|
26
|
+
return @id
|
21
27
|
end
|
22
28
|
|
23
29
|
return self
|
@@ -46,14 +52,9 @@ module Botfly
|
|
46
52
|
|
47
53
|
Botfly.logger.debug(" RSP: Adding to matcher chain: #{@matcher_chain.inspect}")
|
48
54
|
end
|
49
|
-
|
50
|
-
# TODO: Check callback is in acceptable list - MUC subclass can override this list
|
51
|
-
def register_with_bot(callback_type)
|
52
|
-
raise "AbstractMethodError: You must implement this method in a concrete subclass"
|
53
|
-
end
|
54
55
|
|
55
56
|
def setup_instance_variables(params)
|
56
57
|
raise "AbstractMethodError: You must implement this method in a concrete subclass"
|
57
58
|
end
|
58
59
|
end
|
59
|
-
end
|
60
|
+
end
|
data/retrobot.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'botfly'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
config = YAML::load(ARGF.read) if ARGF
|
7
|
+
|
8
|
+
bot = Botfly.login(config["jid"],config["pass"]) do
|
9
|
+
join('lazer').as('retro-bot') do
|
10
|
+
on.message.from(/^rkneufeld/).body(/^rb count/) do
|
11
|
+
say "All votes are now being tallied. You have three votes, use them wisely"
|
12
|
+
say "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
|
13
|
+
room[:votes] = []
|
14
|
+
room[:votes_responder] = on.message.body(/(\d+)+/) do
|
15
|
+
@body.scan(/(\d+)+/).map {|m| room[:votes] << m.first.to_i }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
on.message.from(/^rkneufeld/).body(/^rb stop count/) do
|
19
|
+
say "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
|
20
|
+
say "Allright, voting is finished"
|
21
|
+
remove room[:votes_responder]
|
22
|
+
sorted = room[:votes].inject({}) do |h,n|
|
23
|
+
h[n] ||= 0
|
24
|
+
h[n] += 1
|
25
|
+
h
|
26
|
+
end.sort {|a,b| b[-1] <=> a[-1] }
|
27
|
+
sorted.each {|pair| say "#{pair[0]} => #{pair[-1]} : #{room[:voted][pair[0]].person} - #{room[:voted][pair[0]].name}" }
|
28
|
+
end
|
29
|
+
on.message.from(/^rkneufeld/).body(/^rb tally$/) do
|
30
|
+
room[:tally_responders] = []
|
31
|
+
room[:plus] = {}; room[:minus] = {}; room[:delta] = {}
|
32
|
+
room[:tally_responders] << on.message.body(/^+(.*)/) { room[:plus][from] ||= []; room[:plus][from] << match }
|
33
|
+
room[:tally_responders] << on.message.body(/^∂(.*)/) { room[:delta][from] ||= []; room[:delta][from] << match }
|
34
|
+
room[:tally_responders] << on.message.body(/^-(.*)/) { room[:minus][from] ||= []; room[:minus][from] << match }
|
35
|
+
end
|
36
|
+
on.message.from(/^rkneufeld/).body(/^rb stop tally/) do
|
37
|
+
# remove responders
|
38
|
+
# tally messages
|
39
|
+
# stored to room[:voted]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Thread.stop;loop
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 2
|
7
8
|
- 1
|
8
|
-
|
9
|
-
version: 0.1.1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ryan Neufeld
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-17 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -54,7 +54,6 @@ extra_rdoc_files:
|
|
54
54
|
- LICENSE
|
55
55
|
- README.rdoc
|
56
56
|
files:
|
57
|
-
- .document
|
58
57
|
- .gitignore
|
59
58
|
- LICENSE
|
60
59
|
- README.rdoc
|
@@ -64,15 +63,24 @@ files:
|
|
64
63
|
- example.rb
|
65
64
|
- lib/botfly.rb
|
66
65
|
- lib/botfly/bot.rb
|
66
|
+
- lib/botfly/common_block_acceptor.rb
|
67
67
|
- lib/botfly/matcher.rb
|
68
68
|
- lib/botfly/matcher/body_matcher.rb
|
69
69
|
- lib/botfly/matcher/matcher.rb
|
70
|
+
- lib/botfly/matcher/muc_nick_matcher.rb
|
71
|
+
- lib/botfly/matcher/muc_text_matcher.rb
|
72
|
+
- lib/botfly/matcher/muc_time_matcher.rb
|
70
73
|
- lib/botfly/matcher/nick_matcher.rb
|
71
74
|
- lib/botfly/matcher/subject_matcher.rb
|
75
|
+
- lib/botfly/muc_client.rb
|
72
76
|
- lib/botfly/responder.rb
|
77
|
+
- lib/botfly/responder/common_responder_methods.rb
|
73
78
|
- lib/botfly/responder/message_responder.rb
|
79
|
+
- lib/botfly/responder/muc_message_responder.rb
|
80
|
+
- lib/botfly/responder/muc_responder.rb
|
74
81
|
- lib/botfly/responder/presence_responder.rb
|
75
82
|
- lib/botfly/responder/responder.rb
|
83
|
+
- retrobot.rb
|
76
84
|
- spec/botfly_spec.rb
|
77
85
|
- spec/spec.opts
|
78
86
|
- spec/spec_helper.rb
|