summaryrefslogtreecommitdiff
path: root/rbot/messagemapper.rb
diff options
context:
space:
mode:
authorTom Gilbert <tom@linuxbrit.co.uk>2005-07-27 16:32:32 +0000
committerTom Gilbert <tom@linuxbrit.co.uk>2005-07-27 16:32:32 +0000
commit2a96c9198c1f6e13407d0999083f6ce5e0bc06fa (patch)
treeb3b9247d275d9b554665bc22884104d266d2e757 /rbot/messagemapper.rb
parent21949774b91eaec6ecde4eaa8ad121e2c0a36b87 (diff)
move rbot into lib - still rearranging for packaging/installation
Diffstat (limited to 'rbot/messagemapper.rb')
-rw-r--r--rbot/messagemapper.rb168
1 files changed, 0 insertions, 168 deletions
diff --git a/rbot/messagemapper.rb b/rbot/messagemapper.rb
deleted file mode 100644
index 42563d23..00000000
--- a/rbot/messagemapper.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-module Irc
- class MessageMapper
- attr_writer :fallback
-
- def initialize(parent)
- @parent = parent
- @routes = Array.new
- @fallback = 'usage'
- end
-
- def map(*args)
- @routes << Route.new(*args)
- end
-
- def each
- @routes.each {|route| yield route}
- end
- def last
- @routes.last
- end
-
- def handle(m)
- return false if @routes.empty?
- failures = []
- @routes.each do |route|
- options, failure = route.recognize(m)
- if options.nil?
- failures << [route, failure]
- else
- action = route.options[:action] ? route.options[:action] : route.items[0]
- next unless @parent.respond_to?(action)
- auth = route.options[:auth] ? route.options[:auth] : action
- if m.bot.auth.allow?(auth, m.source, m.replyto)
- debug "route found and auth'd: #{action.inspect} #{options.inspect}"
- @parent.send(action, m, options)
- return true
- end
- # if it's just an auth failure but otherwise the match is good,
- # don't try any more handlers
- break
- end
- end
- debug failures.inspect
- debug "no handler found, trying fallback"
- if @fallback != nil && @parent.respond_to?(@fallback)
- if m.bot.auth.allow?(@fallback, m.source, m.replyto)
- @parent.send(@fallback, m, {})
- return true
- end
- end
- return false
- end
-
- end
-
- class Route
- attr_reader :defaults # The defaults hash
- attr_reader :options # The options hash
- attr_reader :items
- def initialize(template, hash={})
- raise ArgumentError, "Second argument must be a hash!" unless hash.kind_of?(Hash)
- @defaults = hash[:defaults].kind_of?(Hash) ? hash.delete(:defaults) : {}
- @requirements = hash[:requirements].kind_of?(Hash) ? hash.delete(:requirements) : {}
- self.items = template
- @options = hash
- end
- def items=(str)
- items = str.split(/\s+/).collect {|c| (/^(:|\*)(\w+)$/ =~ c) ? (($1 == ':' ) ? $2.intern : "*#{$2}".intern) : c} if str.kind_of?(String) # split and convert ':xyz' to symbols
- items.shift if items.first == ""
- items.pop if items.last == ""
- @items = items
-
- if @items.first.kind_of? Symbol
- raise ArgumentError, "Illegal template -- first component cannot be dynamic\n #{str.inspect}"
- end
-
- # Verify uniqueness of each component.
- @items.inject({}) do |seen, item|
- if item.kind_of? Symbol
- raise ArgumentError, "Illegal template -- duplicate item #{item}\n #{str.inspect}" if seen.key? item
- seen[item] = true
- end
- seen
- end
- end
-
- # Recognize the provided string components, returning a hash of
- # recognized values, or [nil, reason] if the string isn't recognized.
- def recognize(m)
- components = m.message.split(/\s+/)
- options = {}
-
- @items.each do |item|
- if /^\*/ =~ item.to_s
- if components.empty?
- value = @defaults.has_key?(item) ? @defaults[item].clone : []
- else
- value = components.clone
- end
- components = []
- def value.to_s() self.join(' ') end
- options[item.to_s.sub(/^\*/,"").intern] = value
- elsif item.kind_of? Symbol
- value = components.shift || @defaults[item]
- if passes_requirements?(item, value)
- options[item] = value
- else
- if @defaults.has_key?(item)
- debug "item #{item} doesn't pass reqs but has a default of #{@defaults[item]}"
- options[item] = @defaults[item].clone
- # push the test-failed component back on the stack
- components.unshift value
- else
- return nil, requirements_for(item)
- end
- end
- else
- return nil, "No value available for component #{item.inspect}" if components.empty?
- component = components.shift
- return nil, "Value for component #{item.inspect} doesn't match #{component}" if component != item
- end
- end
-
- return nil, "Unused components were left: #{components.join '/'}" unless components.empty?
-
- return nil, "route is not configured for private messages" if @options.has_key?(:private) && !@options[:private] && m.private?
- return nil, "route is not configured for public messages" if @options.has_key?(:public) && !@options[:public] && !m.private?
-
- options.delete_if {|k, v| v.nil?} # Remove nil values.
- return options, nil
- end
-
- def inspect
- when_str = @requirements.empty? ? "" : " when #{@requirements.inspect}"
- default_str = @defaults.empty? ? "" : " || #{@defaults.inspect}"
- "<#{self.class.to_s} #{@items.collect{|c| c.kind_of?(String) ? c : c.inspect}.join(' ').inspect}#{default_str}#{when_str}>"
- end
-
- # Verify that the given value passes this route's requirements
- def passes_requirements?(name, value)
- return @defaults.key?(name) && @defaults[name].nil? if value.nil? # Make sure it's there if it should be
-
- case @requirements[name]
- when nil then true
- when Regexp then
- value = value.to_s
- match = @requirements[name].match(value)
- match && match[0].length == value.length
- else
- @requirements[name] == value.to_s
- end
- end
-
- def requirements_for(name)
- name = name.to_s.sub(/^\*/,"").intern if (/^\*/ =~ name.inspect)
- presence = (@defaults.key?(name) && @defaults[name].nil?)
- requirement = case @requirements[name]
- when nil then nil
- when Regexp then "match #{@requirements[name].inspect}"
- else "be equal to #{@requirements[name].inspect}"
- end
- if presence && requirement then "#{name} must be present and #{requirement}"
- elsif presence || requirement then "#{name} must #{requirement || 'be present'}"
- else "#{name} has no requirements"
- end
- end
- end
-end