Sutto-marvin 0.4.0 → 0.8.0.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.
Files changed (85) hide show
  1. data/bin/marvin +22 -156
  2. data/handlers/keiki_thwopper.rb +21 -0
  3. data/handlers/tweet_tweet.rb +1 -3
  4. data/lib/marvin/abstract_client.rb +75 -189
  5. data/lib/marvin/abstract_parser.rb +9 -11
  6. data/lib/marvin/base.rb +134 -101
  7. data/lib/marvin/client/actions.rb +104 -0
  8. data/lib/marvin/client/default_handlers.rb +97 -0
  9. data/lib/marvin/command_handler.rb +60 -49
  10. data/lib/marvin/console.rb +4 -31
  11. data/lib/marvin/core_commands.rb +30 -12
  12. data/lib/marvin/distributed/client.rb +225 -0
  13. data/lib/marvin/distributed/handler.rb +85 -0
  14. data/lib/marvin/distributed/protocol.rb +88 -0
  15. data/lib/marvin/distributed/server.rb +154 -0
  16. data/lib/marvin/distributed.rb +4 -10
  17. data/lib/marvin/dsl.rb +103 -0
  18. data/lib/marvin/exception_tracker.rb +7 -4
  19. data/lib/marvin/irc/client.rb +127 -99
  20. data/lib/marvin/irc/event.rb +14 -10
  21. data/lib/marvin/irc.rb +0 -1
  22. data/lib/marvin/middle_man.rb +1 -1
  23. data/lib/marvin/parsers/command.rb +10 -8
  24. data/lib/marvin/parsers/prefixes/host_mask.rb +12 -7
  25. data/lib/marvin/parsers/prefixes/server.rb +1 -1
  26. data/lib/marvin/parsers/ragel_parser.rb +59 -52
  27. data/lib/marvin/parsers/ragel_parser.rl +6 -7
  28. data/lib/marvin/parsers/simple_parser.rb +4 -9
  29. data/lib/marvin/parsers.rb +1 -2
  30. data/lib/marvin/settings.rb +29 -79
  31. data/lib/marvin/test_client.rb +20 -26
  32. data/lib/marvin/util.rb +10 -3
  33. data/lib/marvin.rb +42 -39
  34. data/templates/boot.erb +3 -0
  35. data/templates/connections.yml.erb +10 -0
  36. data/templates/debug_handler.erb +5 -0
  37. data/templates/hello_world.erb +10 -0
  38. data/templates/rakefile.erb +15 -0
  39. data/templates/settings.yml.erb +8 -0
  40. data/{config/setup.rb → templates/setup.erb} +8 -10
  41. data/templates/test_helper.erb +17 -0
  42. data/test/abstract_client_test.rb +63 -0
  43. data/test/parser_comparison.rb +2 -2
  44. data/test/parser_test.rb +3 -3
  45. data/test/test_helper.rb +58 -6
  46. metadata +51 -83
  47. data/README.textile +0 -105
  48. data/TUTORIAL.textile +0 -54
  49. data/VERSION.yml +0 -4
  50. data/config/boot.rb +0 -14
  51. data/config/connections.yml.sample +0 -5
  52. data/config/settings.yml.sample +0 -13
  53. data/handlers/logging_handler.rb +0 -89
  54. data/lib/marvin/core_ext.rb +0 -11
  55. data/lib/marvin/daemon.rb +0 -71
  56. data/lib/marvin/data_store.rb +0 -73
  57. data/lib/marvin/dispatchable.rb +0 -99
  58. data/lib/marvin/distributed/dispatch_handler.rb +0 -83
  59. data/lib/marvin/distributed/drb_client.rb +0 -78
  60. data/lib/marvin/distributed/ring_server.rb +0 -41
  61. data/lib/marvin/handler.rb +0 -12
  62. data/lib/marvin/irc/server/abstract_connection.rb +0 -84
  63. data/lib/marvin/irc/server/base_connection.rb +0 -66
  64. data/lib/marvin/irc/server/channel.rb +0 -115
  65. data/lib/marvin/irc/server/named_store.rb +0 -14
  66. data/lib/marvin/irc/server/remote_interface.rb +0 -77
  67. data/lib/marvin/irc/server/user/handle_mixin.rb +0 -140
  68. data/lib/marvin/irc/server/user.rb +0 -5
  69. data/lib/marvin/irc/server/user_connection.rb +0 -134
  70. data/lib/marvin/irc/server/virtual_user_connection.rb +0 -80
  71. data/lib/marvin/irc/server.rb +0 -71
  72. data/lib/marvin/loader.rb +0 -149
  73. data/lib/marvin/logger.rb +0 -86
  74. data/lib/marvin/options.rb +0 -42
  75. data/lib/marvin/parsers/regexp_parser.rb +0 -93
  76. data/lib/marvin/status.rb +0 -72
  77. data/script/client +0 -3
  78. data/script/console +0 -3
  79. data/script/distributed_client +0 -3
  80. data/script/install +0 -1
  81. data/script/ring_server +0 -4
  82. data/script/server +0 -4
  83. data/script/status +0 -3
  84. data/spec/marvin/abstract_client_test.rb +0 -38
  85. data/spec/spec_helper.rb +0 -14
@@ -1,89 +0,0 @@
1
- # A Simple Channel Logger, built for the
2
- # #offrails community. Please note that this
3
- # relies on models etc. inside the Rails App.
4
- # it's suited for modification of subclassing
5
- # if you wish to write your own Channel Logger.
6
- # I plan on open sourcing the app sometime in
7
- # the near future.
8
- class LoggingHandler < Marvin::CommandHandler
9
-
10
- class_inheritable_accessor :connection, :setup
11
- attr_accessor :listening, :users
12
-
13
- def initialize
14
- super
15
- logger.debug "Setting up LoggingHandler"
16
- self.setup!
17
- self.users = {}
18
- end
19
-
20
- # Control
21
-
22
- exposes :listen, :earmuffs
23
-
24
- desc "Makes me listen up and take not of what you're saying."
25
- def listen(data)
26
- unless listening?
27
- @listening = true
28
- reply "Busted! I heard _everything_ you said ;)"
29
- else
30
- reply "Uh, You never asked me to put my earmuffs on?"
31
- end
32
- end
33
-
34
- desc "Sends me off into a corner with my ear muffs so you can have your discussions in peace"
35
- def earmuffs(data)
36
- if listening?
37
- @listening = false
38
- reply "Oh hai, I'm not listening anymore."
39
- else
40
- reply "I've already put the earmuffs on!"
41
- end
42
- end
43
-
44
- def listening?
45
- @listening
46
- end
47
-
48
- # The actual logging
49
-
50
- on_event :incoming_message do
51
- log_message(options.nick, options.target, options.message)
52
- end
53
-
54
- on_event :outgoing_message do
55
- log_message(client.nickname, options.target, options.message)
56
- end
57
-
58
- on_event :incoming_action do
59
- log_message(options.nick, options.target, "ACTION \01#{options.message}\01")
60
- end
61
-
62
- def log_message(from, to, message)
63
- return unless listening?
64
- ensure_connection_is_alive # Before Logging, ensure that the connection is alive.
65
- self.users[from.strip] ||= IrcHandle.find_or_create_by_name(from.strip)
66
- self.users[from.strip].messages.create :message => message, :target => to
67
- end
68
-
69
- # Our General Tasks
70
-
71
- def setup!
72
- return true if self.setup
73
- load_prerequisites
74
- self.setup = true
75
- self.listening = true
76
- end
77
-
78
- def load_prerequisites
79
- require File.join(Marvin::Settings.rails_root, "config/environment")
80
- end
81
-
82
- def ensure_connection_is_alive
83
- unless ActiveRecord::Base.connection.active?
84
- ActiveRecord::Base.connection.reconnect!
85
- end
86
- end
87
-
88
-
89
- end
@@ -1,11 +0,0 @@
1
- class File
2
- def self.present_dir
3
- File.dirname(__FILE__)
4
- end
5
- end
6
-
7
- class String
8
- def /(*args)
9
- File.join(self, *args)
10
- end
11
- end
data/lib/marvin/daemon.rb DELETED
@@ -1,71 +0,0 @@
1
- module Marvin
2
- class Daemon
3
- class << self
4
-
5
- def alive?(pid)
6
- return Process.getpgid(pid) != -1
7
- rescue Errno::ESRCH
8
- return false
9
- end
10
-
11
- def kill_all(type = :all)
12
- if type == :all
13
- files = Dir[Marvin::Settings.root / "tmp/pids/*.pid"]
14
- files.each { |f| kill_all_from f }
15
- elsif type.is_a?(Symbol)
16
- kill_all_from(pid_file_for(type))
17
- end
18
- return nil
19
- end
20
-
21
- def daemonize!
22
- exit if fork
23
- Process.setsid
24
- exit if fork
25
- self.write_pid
26
- File.umask 0000
27
- STDIN.reopen "/dev/null"
28
- STDOUT.reopen "/dev/null", "a"
29
- STDERR.reopen STDOUT
30
- Marvin::Settings.verbose = false
31
- end
32
-
33
- def cleanup!
34
- f = pids_file_for(Marvin::Loader.type)
35
- FileUtils.rm_f(f) if (pids_from(f) - Process.pid).blank?
36
- end
37
-
38
- def pids_for_type(type)
39
- pids_from(pid_file_for(type))
40
- end
41
-
42
- protected
43
-
44
- def kill_all_from(file)
45
- pids = pids_from(file)
46
- pids.each { |p| Process.kill("TERM", p) unless p == Process.pid }
47
- FileUtils.rm_f(file)
48
- rescue => e
49
- STDOUT.puts e.inspect
50
- end
51
-
52
- def pid_file_for(type)
53
- Marvin::Settings.root / "tmp" / "pids" / "marvin-#{type.to_s.underscore}.pid"
54
- end
55
-
56
- def pids_from(file)
57
- return [] unless File.exist?(file)
58
- pids = File.read(file)
59
- pids = pids.split("\n").map { |l| l.strip.to_i(10) }.select { |p| alive?(p) }
60
- end
61
-
62
- def write_pid
63
- f = pid_file_for(Marvin::Loader.type)
64
- pids = pids_from(f)
65
- pids << Process.pid unless pids.include?(Process.pid)
66
- File.open(f, "w+") { |f| f.puts pids.join("\n") }
67
- end
68
-
69
- end
70
- end
71
- end
@@ -1,73 +0,0 @@
1
- require 'json'
2
-
3
- module Marvin
4
- # Implements a simple datastore interface, designed to make
5
- # it easy to develop handlers which have persistent data.
6
- class DataStore
7
-
8
- cattr_accessor :logger, :registered_stores
9
- self.logger = Marvin::Logger.logger
10
- self.registered_stores = {}
11
-
12
- # Returns the path to the data store relative to this file.
13
- # Used when loading / dumping the data.
14
- def self.datastore_location
15
- path = Marvin::Settings[:datastore_location] ? Marvin::Settings.datastore_location : "tmp/datastore.json"
16
- return Marvin::Settings.root / path
17
- end
18
-
19
- # Dump the current data store contents to file.
20
- def self.dump!
21
- File.open(self.datastore_location, "w+") do |f|
22
- f.write self.registered_stores.to_json
23
- end
24
- end
25
-
26
- # Load the current data store contents from file.
27
- def self.load!
28
- results = {}
29
- if File.exists?(self.datastore_location)
30
- begin
31
- json = JSON.load(File.read(self.datastore_location))
32
- results = json if json.is_a?(Hash)
33
- rescue JSON::ParserError
34
- end
35
- end
36
- self.registered_stores = results
37
- end
38
-
39
-
40
- # For each individual datastore.
41
-
42
- attr_accessor :name
43
-
44
- def initialize(name)
45
- self.name = name.to_s
46
- self.registered_stores ||= {}
47
- self.registered_stores[self.name] ||= {}
48
- end
49
-
50
- def [](key)
51
- ((self.registered_stores||={})[self.name]||={})[key.to_s]
52
- end
53
-
54
- def []=(key,value)
55
- self.registered_stores[self.name][key.to_s] = value
56
- end
57
-
58
- def method_missing(name, *args, &blk)
59
- if name.to_s =~ /^(.*)=$/i
60
- self[$1.to_s] = args.first
61
- elsif self.registered_stores[self.name].has_key?(name.to_s)
62
- return self.registered_stores[self.name][name.to_s]
63
- else
64
- super(name, *args, &blk)
65
- end
66
- end
67
-
68
- def to_hash
69
- self.registered_stores[self.name]
70
- end
71
-
72
- end
73
- end
@@ -1,99 +0,0 @@
1
- module Marvin
2
- # = Marvin::Dispatchable
3
- # A Generic mixin which lets you define an object
4
- # Which accepts handlers which can have arbitrary
5
- # events dispatched.
6
- # == Usage
7
- #
8
- # class X
9
- # include Marvin::Dispatchable
10
- # self.handlers << SomeHandler.new
11
- # end
12
- # X.new.dispatch(:name, {:args => "Values"})
13
- #
14
- # Will first check if SomeHandler#handle_name exists,
15
- # calling handle_name({:args => "Values"}) if it does,
16
- # otherwise calling SomeHandler#handle(:name, {:args => "Values"})
17
- module Dispatchable
18
-
19
- def self.included(parent)
20
- parent.class_eval do
21
- include InstanceMethods
22
- extend ClassMethods
23
- end
24
- end
25
-
26
- module InstanceMethods
27
-
28
- # Returns the handlers registered on this class,
29
- # used inside +dispatch+. Note that it will call
30
- # dup on each of the objects to get a new instance.
31
- # please ensure your object acts accordingly.
32
- def handlers
33
- @handlers ||= self.class.handlers.map { |h| h.dup }
34
- end
35
-
36
- # Dispatch an 'event' with a given name to the handlers
37
- # registered on the current class. Used as a nicer way of defining
38
- # behaviours that should occur under a given set of circumstances.
39
- # == Params
40
- # +name+: The name of the current event
41
- # +opts+: an optional hash of options to pass
42
- def dispatch(name, opts = {})
43
- # The full handler name is the method we call given it exists.
44
- full_handler_name = :"handle_#{name.to_s.underscore}"
45
- # First, dispatch locally if the method is defined.
46
- if self.respond_to?(full_handler_name)
47
- self.send(full_handler_name, opts)
48
- end
49
- # Iterate through all of the registered handlers,
50
- # If there is a method named handle_<event_name>
51
- # defined we sent that otherwise we call the handle
52
- # method on the handler. Note that the handle method
53
- # is the only required aspect of a handler. An improved
54
- # version of this would likely cache the respond_to?
55
- # call.
56
- self.handlers.each do |handler|
57
- if handler.respond_to?(full_handler_name)
58
- handler.send(full_handler_name, opts)
59
- else
60
- handler.handle name, opts
61
- end
62
- end
63
- # If we get the HaltHandlerProcessing exception, we
64
- # catch it and continue on our way. In essence, we
65
- # stop the dispatch of events to the next set of the
66
- # handlers.
67
- rescue HaltHandlerProcessing => e
68
- Marvin::Logger.info "Halting processing chain"
69
- rescue Exception => e
70
- Marvin::ExceptionTracker.log(e)
71
- end
72
-
73
- end
74
-
75
- module ClassMethods
76
-
77
- # Return an array of all registered handlers, stored in the
78
- # class variable @@handlers. Used inside the #handlers instance
79
- # method as well as inside things such as register_handler.
80
- def handlers
81
- @@handlers ||= []
82
- end
83
-
84
- # Assigns a new array of handlers and assigns each.
85
- def handlers=(new_value)
86
- @@handlers = []
87
- new_value.to_a.each { |h| register_handler h }
88
- end
89
-
90
- # Appends a handler to the list of handlers for this object.
91
- # Handlers are called in the order they are registered.
92
- def register_handler(handler)
93
- self.handlers << handler unless handler.nil? || !handler.respond_to?(:handle)
94
- end
95
-
96
- end
97
-
98
- end
99
- end
@@ -1,83 +0,0 @@
1
- require 'rinda/ring'
2
- require 'rinda/tuplespace'
3
-
4
- DRb.start_service
5
-
6
- module Marvin
7
- module Distributed
8
-
9
- # Handler to provide
10
- class DispatchHandler < Marvin::Base
11
-
12
- LOOKUP_TIMEOUT = 0.5
13
-
14
- # Tell the client that we shouldn't be dumped.
15
- Marvin::AbstractClient.class_eval { include(DRbUndumped) }
16
-
17
- # Get the ring server - if it exists, we will return the current
18
- # instance other wise it follows a few steps to try and find a new
19
- # one. Since there can be a delay in getting a response, we'll only
20
- # check every 5 messages.
21
- def ring_server
22
- if @@rs.nil? && (@lookup_attempts ||= 6) > 5
23
- @lookup_attempts = 0
24
- @@rs = Rinda::RingFinger.finger.lookup_ring(LOOKUP_TIMEOUT)
25
- logger.info "Found new ring server => #{@@rs.__drburi}"
26
- elsif @@rs.nil?
27
- @lookup_attempts += 1
28
- end
29
- return @@rs
30
- rescue RingNotFound
31
- @@rs = nil
32
- end
33
-
34
- # Takes an incoming messsage and does all the fancy
35
- # Stuff with it.
36
- def handle(message, options)
37
- # Don't forward lines for the moment to halve the traffic.
38
- return if message == :incoming_line
39
- super(message, options)
40
- dispatch(message, options)
41
- end
42
-
43
- # Attempts to add a message to the current tuple space,
44
- # adding it to a message queue if it can't be added.
45
- # If there are many items, it will log a warning.
46
- # TODO: Improve it to dump messages to disk at a predefined limit.
47
- def dispatch(name, options)
48
- options[:dispatched_at] ||= Time.now
49
- tuple = [:marvin_event, Marvin::Settings.distributed_namespace, name, options, self.client]
50
- begin
51
- (@queued_messages ||= []) << tuple
52
- if self.ring_server.nil?
53
- size = @queued_messages.size
54
- if size > 0 && size % 25 == 0
55
- logger.warn "Dispatch handler queue is currently holding #{size} items"
56
- end
57
- else
58
- logger.debug "Writing #{@queued_messages.size} message to the ring server"
59
- @queued_messages.dup.each do |t|
60
- ring_server.write(t)
61
- @queued_messages.delete(t)
62
- end
63
- end
64
- rescue
65
- # Reset the ring finger to the next choice.
66
- logger.debug "Ring server unavailable, resetting..."
67
- @@rs = nil
68
- end
69
- end
70
-
71
- # Register this as a handler, but only if we're
72
- # running in "client mode" - in other words, we
73
- # want to make sure it won't start up an infinite
74
- # loop.
75
- def self.register!(*args)
76
- # DO NOT register if this is not a normal client.
77
- return unless Marvin::Loader.type == :client
78
- super
79
- end
80
-
81
- end
82
- end
83
- end
@@ -1,78 +0,0 @@
1
- module Marvin
2
- module Distributed
3
- # A method for operating on marvin objects.
4
- class DRbClient
5
-
6
- # Wait 1 second on a lookup.
7
- LOOKUP_TIMEOUT = 1
8
-
9
- class << self
10
-
11
- @@handlers = []
12
- attr_accessor :stopped
13
-
14
- def register_handler(handler)
15
- @@handlers << handler unless handler.nil? || !handler.respond_to?(:handle)
16
- end
17
-
18
- def dispatch(name, opts, client)
19
- Marvin::Logger.debug "Processing Event: #{name}"
20
- full_handler_name = :"handle_#{name.to_s.underscore}"
21
- @@handlers.each do |handler|
22
- has_client = handler.respond_to?(:client=)
23
- handler.client = client if has_client
24
- if handler.respond_to?(full_handler_name)
25
- handler.send(full_handler_name, opts)
26
- else
27
- handler.handle name, opts
28
- end
29
- handler.client = nil if has_client
30
- end
31
- rescue HaltHandlerProcessing => e
32
- Marvin::Logger.info "Halting processing chain"
33
- rescue Exception => e
34
- Marvin::ExceptionTracker.log(e)
35
- end
36
-
37
- # Starts up a drb processor / client, and walks through the process of dealing
38
- # with it / processing events.
39
- def run
40
- self.stopped = false
41
- Marvin::Logger.info "Starting up DRb Client"
42
- DRb.start_service
43
- # Loop through, making sure we have a valid
44
- # RingFinger and then process events as they
45
- # appear.
46
- enter_loop!
47
- end
48
-
49
- def stop
50
- self.stopped = true
51
- end
52
-
53
- def ring_server
54
- @ring_server = Rinda::RingFinger.finger.lookup_ring(LOOKUP_TIMEOUT) if @ring_server.nil?
55
- return @ring_server
56
- rescue RingNotFound
57
- @ring_server = nil
58
- end
59
-
60
- def enter_loop!
61
- Marvin::Logger.info "Entering processing loop"
62
- while !self.stopped
63
- begin
64
- unless self.ring_server.blank?
65
- event = self.ring_server.take([:marvin_event, Marvin::Settings.distributed_namespace, nil, nil, nil], 2)
66
- dispatch(*event[2..-1]) unless event.blank?
67
- end
68
- rescue
69
- # Reset the ring server on event of connection refused etc.
70
- @ring_server = nil
71
- end
72
- end
73
- end
74
-
75
- end
76
- end
77
- end
78
- end
@@ -1,41 +0,0 @@
1
- require 'rinda/ring'
2
- require 'rinda/tuplespace'
3
-
4
- module Marvin
5
- module Distributed
6
- class RingServer
7
-
8
- attr_accessor :tuple_space, :ring_server
9
- cattr_accessor :logger
10
- self.logger = Marvin::Logger
11
-
12
- def initialize
13
- self.tuple_space = Rinda::TupleSpace.new
14
- if Marvin::Settings.log_level == :debug
15
- observer = self.tuple_space.notify('write', [:marvin_event, Marvin::Settings.distributed_namespace, nil, nil, nil])
16
- Thread.start do
17
- observer.each do |i|
18
- event_name, args = i[1][2..3]
19
- Marvin::Logger.logger.debug "Marvin event added - #{event_name.inspect} w/ #{args.inspect}"
20
- end
21
- end
22
- end
23
- self.ring_server = Rinda::RingServer.new(self.tuple_space)
24
- end
25
-
26
- def self.run
27
- begin
28
- logger.info "Starting up DRb"
29
- drb_server = DRb.start_service
30
- logger.info "Creating TupleSpace & Ring Server Instances - Running on #{DRb.uri}"
31
- self.new
32
- logger.info "Started - Joining thread."
33
- DRb.thread.join
34
- rescue
35
- logger.fatal "Error starting ring server - please ensure another instance isn't already running."
36
- end
37
- end
38
-
39
- end
40
- end
41
- end
@@ -1,12 +0,0 @@
1
- module Marvin
2
- module Handler
3
-
4
- # Received a given +message+ with a set of default
5
- # +opts+ (defaulting back to an empty hash), which
6
- # will be used to perform some sort of action.
7
- def handle(message, opts = {})
8
- Marvin::Logger.debug "NOP handle - got message #{message.inspect}"
9
- end
10
-
11
- end
12
- end
@@ -1,84 +0,0 @@
1
- module Marvin::IRC::Server
2
- class AbstractConnection
3
- include Marvin::Dispatchable
4
-
5
- cattr_accessor :connections, :logger, :alive
6
- self.connections = []
7
- self.logger = Marvin::Logger
8
-
9
- attr_accessor :connection
10
-
11
- # Create a new connection with a given parent
12
- # and an incoming buffer of messages
13
- def initialize(parent, buffer = [])
14
- @connection = parent
15
- buffer.each { |line| receive_line(line) }
16
- end
17
-
18
- def receive_line(line)
19
- dispatch :incoming_line, :line => line
20
- event = Marvin::Settings.default_parser.parse(line)
21
- dispatch(event.to_incoming_event_name, event.to_hash) unless event.nil?
22
- end
23
-
24
- def send_line(line)
25
- @connection.send_line(line)
26
- end
27
-
28
- def process_connect
29
- @alive = true
30
- # Send the welcome notice / auth command.
31
- command :NOTICE, "AUTH", ":Marvin v#{Marvin.version} initialized, welcome."
32
- dispatch :client_connected, :client => self
33
- end
34
-
35
- def process_disconnect
36
- @@connections.delete(self)
37
- @alive = false
38
- dispatch :client_disconnected, :client => self
39
- end
40
-
41
- class << self
42
-
43
- # Return an array of all registered handlers, stored in the
44
- # class variable @@handlers. Used inside the #handlers instance
45
- # method as well as inside things such as register_handler.
46
- def handlers
47
- (@@handlers ||= {})[self] ||= []
48
- end
49
-
50
- # Assigns a new array of handlers and assigns each.
51
- def handlers=(new_value)
52
- (@@handlers ||= {})[self] = []
53
- new_value.to_a.each { |h| register_handler h }
54
- end
55
-
56
- end
57
-
58
- def dispatch(name, opts = {})
59
- opts[:connection] ||= self
60
- super
61
- end
62
-
63
- private
64
-
65
- def command(name, *args)
66
- opts = args.extract_options!
67
- formatted = [name.to_s.upcase, *args].join(" ")
68
- formatted = ":#{opts[:prefix]} #{formatted}" if opts[:prefix]
69
- send_line formatted
70
- end
71
-
72
- def peer_name
73
- return @peer_name unless @peer_name.blank?
74
- sock_addr = @connection.get_peername
75
- begin
76
- @peer_name = Socket.getnameinfo(sock_addr, Socket::NI_NAMEREQD).first
77
- rescue
78
- @peer_name = Socket.getnameinfo(sock_addr).first
79
- end
80
- return @peer_name
81
- end
82
-
83
- end
84
- end