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.
@@ -1,9 +1,19 @@
1
- = botfly
1
+ = Botfly
2
2
 
3
- Description goes here.
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.1
1
+ 0.2.1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{botfly}
8
- s.version = "0.1.1"
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-13}
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
- ".document",
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(:message).body(/^exit$/) { reply "Goodbye!"; quit }
13
- on(:message).nick(/rkneufeld/) do
14
- Botfly.logger.info("Callback called")
15
- @count ||= 0
16
- @count += 1
17
- reply("That's the #{@count}th message I've received.")
18
- end
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
- on(:presence) { puts self }
21
- connect
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
- Thread.stop
24
- loop{}
38
+
39
+ Thread.stop;loop
@@ -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
- require 'logger'
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.instance_eval(&block)
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
@@ -1,14 +1,15 @@
1
1
  require 'rubygems'
2
2
 
3
3
  module Botfly
4
- class Bot
5
- attr_reader :responders, :client
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
- register_for_xmpp_callbacks
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 on(type, &block)
26
- Botfly.logger.info(" BOT: Bot#on")
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 register_for_xmpp_callbacks
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,new_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 = params[:muc] ? @muc_responders[params[:muc]] : @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
@@ -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 " MCH: Matching #{@condition.inspect} against #{msg.body.inspect}"
9
- Botfly.logger.debug " RESULT: #{(msg.body =~ @condition).inspect}"
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
@@ -1,7 +1,7 @@
1
1
  module Botfly
2
2
  class Matcher
3
3
  def initialize(condition)
4
- Botfly.logger.info(" MCH: Creating Matcher")
4
+ Botfly.logger.info("MCH: Creating Matcher")
5
5
  @condition = condition
6
6
  end
7
7
  def match(params)
@@ -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 " MCH: Matching #{@condition.inspect} against #{msg.from.inspect}"
9
- Botfly.logger.debug " RESULT: #{(msg.from.node =~ @condition).inspect}"
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 " MCH: Matching #{@condition.inspect} against #{msg.subject.inspect}"
9
- Botfly.logger.debug " RESULT: #{(msg.subject =~ @condition).inspect}"
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
@@ -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(" RSP: MessageResponder setting up instance variables")
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(" RSP: MessageResponder#reply called")
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,4 @@
1
+ module Botfly
2
+ class MUCMessageResponder < MUCResponder
3
+ end
4
+ end
@@ -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
- attr_reader :callback, :callback_type
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(client,bot,&block)
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
@@ -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
- - 1
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-13 00:00:00 -06:00
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
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE