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.
- data/bin/marvin +22 -156
- data/handlers/keiki_thwopper.rb +21 -0
- data/handlers/tweet_tweet.rb +1 -3
- data/lib/marvin/abstract_client.rb +75 -189
- data/lib/marvin/abstract_parser.rb +9 -11
- data/lib/marvin/base.rb +134 -101
- data/lib/marvin/client/actions.rb +104 -0
- data/lib/marvin/client/default_handlers.rb +97 -0
- data/lib/marvin/command_handler.rb +60 -49
- data/lib/marvin/console.rb +4 -31
- data/lib/marvin/core_commands.rb +30 -12
- data/lib/marvin/distributed/client.rb +225 -0
- data/lib/marvin/distributed/handler.rb +85 -0
- data/lib/marvin/distributed/protocol.rb +88 -0
- data/lib/marvin/distributed/server.rb +154 -0
- data/lib/marvin/distributed.rb +4 -10
- data/lib/marvin/dsl.rb +103 -0
- data/lib/marvin/exception_tracker.rb +7 -4
- data/lib/marvin/irc/client.rb +127 -99
- data/lib/marvin/irc/event.rb +14 -10
- data/lib/marvin/irc.rb +0 -1
- data/lib/marvin/middle_man.rb +1 -1
- data/lib/marvin/parsers/command.rb +10 -8
- data/lib/marvin/parsers/prefixes/host_mask.rb +12 -7
- data/lib/marvin/parsers/prefixes/server.rb +1 -1
- data/lib/marvin/parsers/ragel_parser.rb +59 -52
- data/lib/marvin/parsers/ragel_parser.rl +6 -7
- data/lib/marvin/parsers/simple_parser.rb +4 -9
- data/lib/marvin/parsers.rb +1 -2
- data/lib/marvin/settings.rb +29 -79
- data/lib/marvin/test_client.rb +20 -26
- data/lib/marvin/util.rb +10 -3
- data/lib/marvin.rb +42 -39
- data/templates/boot.erb +3 -0
- data/templates/connections.yml.erb +10 -0
- data/templates/debug_handler.erb +5 -0
- data/templates/hello_world.erb +10 -0
- data/templates/rakefile.erb +15 -0
- data/templates/settings.yml.erb +8 -0
- data/{config/setup.rb → templates/setup.erb} +8 -10
- data/templates/test_helper.erb +17 -0
- data/test/abstract_client_test.rb +63 -0
- data/test/parser_comparison.rb +2 -2
- data/test/parser_test.rb +3 -3
- data/test/test_helper.rb +58 -6
- metadata +51 -83
- data/README.textile +0 -105
- data/TUTORIAL.textile +0 -54
- data/VERSION.yml +0 -4
- data/config/boot.rb +0 -14
- data/config/connections.yml.sample +0 -5
- data/config/settings.yml.sample +0 -13
- data/handlers/logging_handler.rb +0 -89
- data/lib/marvin/core_ext.rb +0 -11
- data/lib/marvin/daemon.rb +0 -71
- data/lib/marvin/data_store.rb +0 -73
- data/lib/marvin/dispatchable.rb +0 -99
- data/lib/marvin/distributed/dispatch_handler.rb +0 -83
- data/lib/marvin/distributed/drb_client.rb +0 -78
- data/lib/marvin/distributed/ring_server.rb +0 -41
- data/lib/marvin/handler.rb +0 -12
- data/lib/marvin/irc/server/abstract_connection.rb +0 -84
- data/lib/marvin/irc/server/base_connection.rb +0 -66
- data/lib/marvin/irc/server/channel.rb +0 -115
- data/lib/marvin/irc/server/named_store.rb +0 -14
- data/lib/marvin/irc/server/remote_interface.rb +0 -77
- data/lib/marvin/irc/server/user/handle_mixin.rb +0 -140
- data/lib/marvin/irc/server/user.rb +0 -5
- data/lib/marvin/irc/server/user_connection.rb +0 -134
- data/lib/marvin/irc/server/virtual_user_connection.rb +0 -80
- data/lib/marvin/irc/server.rb +0 -71
- data/lib/marvin/loader.rb +0 -149
- data/lib/marvin/logger.rb +0 -86
- data/lib/marvin/options.rb +0 -42
- data/lib/marvin/parsers/regexp_parser.rb +0 -93
- data/lib/marvin/status.rb +0 -72
- data/script/client +0 -3
- data/script/console +0 -3
- data/script/distributed_client +0 -3
- data/script/install +0 -1
- data/script/ring_server +0 -4
- data/script/server +0 -4
- data/script/status +0 -3
- data/spec/marvin/abstract_client_test.rb +0 -38
- data/spec/spec_helper.rb +0 -14
data/lib/marvin/dsl.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# Handy Dandy DSL style stuff for Marvin
|
2
|
+
module Marvin
|
3
|
+
class DSL
|
4
|
+
|
5
|
+
class Proxy < Perennial::Proxy
|
6
|
+
|
7
|
+
def initialize(klass)
|
8
|
+
@prototype_klass = Class.new(klass)
|
9
|
+
@mapping = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_shortcut(name, method_name)
|
13
|
+
@mapping[name] = method_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def shortdef(hash = {})
|
17
|
+
hash.each_pair { |k,v| define_shortcut(k, v) }
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def initialize_class!
|
23
|
+
@klass = Class.new(@prototype_klass)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_instance
|
27
|
+
@klass.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_class
|
31
|
+
@klass
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(name, *args, &blk)
|
35
|
+
name = name.to_sym
|
36
|
+
if @mapping.has_key?(name)
|
37
|
+
@klass.define_method(@mapping[name], &blk)
|
38
|
+
else
|
39
|
+
@klass.send(name, *args, &blk)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(&blk)
|
46
|
+
instance_eval(&blk)
|
47
|
+
end
|
48
|
+
|
49
|
+
def logging(&blk)
|
50
|
+
call_prototype(:logging, &blk).register!
|
51
|
+
end
|
52
|
+
|
53
|
+
def handler(&blk)
|
54
|
+
call_prototype(:handler, &blk).register!
|
55
|
+
end
|
56
|
+
|
57
|
+
def commands(&blk)
|
58
|
+
call_prototype(:commands, &blk).register!
|
59
|
+
end
|
60
|
+
|
61
|
+
def configure(&blk)
|
62
|
+
Marvin::Settings.client.configure(&blk)
|
63
|
+
end
|
64
|
+
|
65
|
+
def server(name, port = nil)
|
66
|
+
name = name.to_s.dup
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
def initialize_prototypes
|
74
|
+
prototype_for(:logging, Marvin::LoggingHandler) do
|
75
|
+
shortdef :setup => :setup_logging,
|
76
|
+
:teardown => :teardown_logging,
|
77
|
+
:incoming => :log_incoming,
|
78
|
+
:outgoing => :log_outgoing,
|
79
|
+
:message => :log_message
|
80
|
+
end
|
81
|
+
prototype_for(:handler, Marvin::Base) do
|
82
|
+
map :on => :on_event,
|
83
|
+
:numeric => :on_numeric
|
84
|
+
end
|
85
|
+
prototype_for(:handler, Marvin::CommandHandler)
|
86
|
+
end
|
87
|
+
|
88
|
+
def prototype_for(name, klass, &blk)
|
89
|
+
@prototypes ||= {}
|
90
|
+
p = Proxy.new(klass)
|
91
|
+
p.instance_eval(&blk)
|
92
|
+
@prototypes[name] = p
|
93
|
+
end
|
94
|
+
|
95
|
+
def call_prototype(name, &blk)
|
96
|
+
p = @prototypes[name]
|
97
|
+
p.initialize_class!
|
98
|
+
p.instance_eval(&blk)
|
99
|
+
return p.to_class
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -1,15 +1,18 @@
|
|
1
1
|
module Marvin
|
2
2
|
class ExceptionTracker
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
is :loggable
|
5
|
+
|
6
|
+
cattr_accessor :log_exception_proc
|
7
|
+
self.log_exception_proc = proc { |e| e }
|
6
8
|
|
7
9
|
def self.log(e)
|
8
|
-
logger.fatal "
|
9
|
-
logger.fatal "#{e}
|
10
|
+
logger.fatal "Oh noes cap'n - we have an exception!."
|
11
|
+
logger.fatal "#{e.class.name}: #{e.message}"
|
10
12
|
e.backtrace.each do |line|
|
11
13
|
logger.fatal line
|
12
14
|
end
|
15
|
+
@@log_exception_proc.call(e)
|
13
16
|
end
|
14
17
|
|
15
18
|
end
|
data/lib/marvin/irc/client.rb
CHANGED
@@ -1,138 +1,166 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
|
3
3
|
module Marvin::IRC
|
4
|
-
|
5
|
-
# == Marvin::IRC::Client
|
6
|
-
# An EventMachine protocol implementation built to
|
7
|
-
# serve as a basic, single server IRC client.
|
8
|
-
#
|
9
|
-
# Operates on the principal of Events as well
|
10
|
-
# as handlers.
|
11
|
-
#
|
12
|
-
# === Events
|
13
|
-
# Events are things that can happen (e.g. an
|
14
|
-
# incoming message). All outgoing events are
|
15
|
-
# automatically handled from within the client
|
16
|
-
# class. Incoming events are currently based
|
17
|
-
# on regular expression based matches of
|
18
|
-
# incoming messages. the Client#register_event
|
19
|
-
# method takes either an instance of Marvin::IRC::Event
|
20
|
-
# or a set of arguments which will then be used
|
21
|
-
# in the constructor of a new Marvin::IRC::Event
|
22
|
-
# instance (see, for example, the source code for
|
23
|
-
# this class for examples).
|
24
|
-
#
|
25
|
-
# === Handlers
|
26
|
-
# Handlers on the other hand do as the name suggests
|
27
|
-
# - they listen for dispatched events and act accordingly.
|
28
|
-
# Handlers are simply objects which follow a certain
|
29
|
-
# set of guidelines. Typically, a handler will at
|
30
|
-
# minimum respond to #handle(event_name, details)
|
31
|
-
# where event_name is a symbol for the current
|
32
|
-
# event (e.g. :incoming_event) whilst details is a
|
33
|
-
# a hash of details about the current event (e.g.
|
34
|
-
# message target and the message itself).
|
35
|
-
#
|
36
|
-
# ==== Getting the current client instance
|
37
|
-
# If the object responds to client=, The client will
|
38
|
-
# call it with the current instance of itself
|
39
|
-
# enabling the handler to do things such as respond.
|
40
|
-
# Also, if a method handle_[message_name] exists,
|
41
|
-
# it will be called instead of handle.
|
42
|
-
#
|
43
|
-
# ==== Adding handlers
|
44
|
-
# To add an object as a handler, you simply call
|
45
|
-
# the class method, register_handler with the
|
46
|
-
# handler as the only argument.
|
47
4
|
class Client < Marvin::AbstractClient
|
48
|
-
|
49
|
-
|
5
|
+
|
6
|
+
@@stopped = false
|
50
7
|
|
51
8
|
attr_accessor :em_connection
|
52
9
|
|
53
10
|
class EMConnection < EventMachine::Protocols::LineAndTextProtocol
|
54
|
-
|
11
|
+
is :loggable
|
12
|
+
|
13
|
+
attr_accessor :client, :port, :configuration
|
55
14
|
|
56
15
|
def initialize(*args)
|
57
|
-
|
16
|
+
@configuration = args.last.is_a?(Marvin::Nash) ? args.pop : Marvin::Nash.new
|
58
17
|
super(*args)
|
59
|
-
|
60
|
-
|
18
|
+
@client = Marvin::IRC::Client.new(@configuration)
|
19
|
+
@client.em_connection = self
|
20
|
+
@connected = false
|
21
|
+
rescue Exception => e
|
22
|
+
Marvin::ExceptionTracker.log(e)
|
23
|
+
Marvin::IRC::Client.stop
|
61
24
|
end
|
62
25
|
|
63
26
|
def post_init
|
64
|
-
client.process_connect
|
65
27
|
super
|
28
|
+
if should_use_ssl?
|
29
|
+
logger.info "Starting SSL for #{host_with_port}"
|
30
|
+
start_tls
|
31
|
+
else
|
32
|
+
connected!
|
33
|
+
end
|
34
|
+
rescue Exception => e
|
35
|
+
Marvin::ExceptionTracker.log(e)
|
36
|
+
Marvin::IRC::Client.stop
|
37
|
+
end
|
38
|
+
|
39
|
+
def ssl_handshake_completed
|
40
|
+
logger.info "SSL handshake completed for #{host_with_port}"
|
41
|
+
connected! if should_use_ssl?
|
42
|
+
rescue Exception => e
|
43
|
+
Marvin::ExceptionTracker.log(e)
|
44
|
+
Marvin::IRC::Client.stop
|
66
45
|
end
|
67
46
|
|
68
47
|
def unbind
|
69
|
-
client.process_disconnect
|
48
|
+
@client.process_disconnect
|
70
49
|
super
|
71
50
|
end
|
72
51
|
|
73
52
|
def receive_line(line)
|
74
|
-
|
75
|
-
|
53
|
+
return unless @connected
|
54
|
+
line = line.strip
|
55
|
+
logger.debug "<< #{line}"
|
56
|
+
@client.receive_line(line)
|
57
|
+
rescue Exception => e
|
58
|
+
logger.warn "Uncaught exception raised; Likely in Marvin"
|
59
|
+
Marvin::ExceptionTracker.log(e)
|
76
60
|
end
|
77
61
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
## Client specific details
|
86
|
-
|
87
|
-
# Starts the EventMachine loop and hence starts up the actual
|
88
|
-
# networking portion of the IRC Client.
|
89
|
-
def self.run(force = false)
|
90
|
-
return if self.stopped && !force
|
91
|
-
self.setup # So we have options etc
|
92
|
-
settings = YAML.load_file(Marvin::Settings.root / "config/connections.yml")
|
93
|
-
if settings.is_a?(Hash)
|
94
|
-
# Use epoll if available
|
95
|
-
EventMachine.epoll
|
96
|
-
EventMachine::run do
|
97
|
-
settings.each do |name, options|
|
98
|
-
settings = options.symbolize_keys!
|
99
|
-
settings[:server] ||= name
|
100
|
-
settings.reverse_merge!(:port => 6667, :channels => [])
|
101
|
-
connect settings
|
102
|
-
end
|
62
|
+
def send_line(*lines)
|
63
|
+
return unless @connected
|
64
|
+
lines.each do |line|
|
65
|
+
logger.debug ">> #{line.strip}"
|
66
|
+
send_data line
|
103
67
|
end
|
104
|
-
else
|
105
|
-
logger.fatal "config/connections.yml couldn't be loaded. Exiting"
|
106
68
|
end
|
69
|
+
|
70
|
+
def connected!
|
71
|
+
@connected = true
|
72
|
+
@client.process_connect
|
73
|
+
end
|
74
|
+
|
75
|
+
def should_use_ssl?
|
76
|
+
@should_use_ssl ||= @configuration.ssl?
|
77
|
+
end
|
78
|
+
|
79
|
+
def host_with_port
|
80
|
+
"#{@configuration.host}:#{@configuration.port}"
|
81
|
+
end
|
82
|
+
|
107
83
|
end
|
108
84
|
|
109
|
-
|
110
|
-
logger.info "Connecting to #{opts[:server]}:#{opts[:port]} - Channels: #{opts[:channels].join(", ")}"
|
111
|
-
EventMachine::connect(opts[:server], opts[:port], EMConnection, opts)
|
112
|
-
end
|
85
|
+
## Client specific details
|
113
86
|
|
114
|
-
def
|
115
|
-
|
116
|
-
logger.debug "Telling all connections to quit"
|
117
|
-
self.connections.dup.each { |connection| connection.quit }
|
118
|
-
logger.debug "Telling Event Machine to Stop"
|
119
|
-
EventMachine::stop_event_loop
|
120
|
-
logger.debug "Stopped."
|
121
|
-
self.stopped = true
|
87
|
+
def send_line(*args)
|
88
|
+
@em_connection.send_line(*args)
|
122
89
|
end
|
123
90
|
|
124
|
-
|
125
|
-
|
126
|
-
EventMachine
|
127
|
-
|
128
|
-
|
91
|
+
class << self
|
92
|
+
|
93
|
+
# Starts the EventMachine loop and hence starts up the actual
|
94
|
+
# networking portion of the IRC Client.
|
95
|
+
def run(opts = {}, force = false)
|
96
|
+
self.development = opts[:development]
|
97
|
+
return if @stopped && !force
|
98
|
+
self.setup # So we have options etc
|
99
|
+
connections_file = Marvin::Settings.root / "config" / "connections.yml"
|
100
|
+
connections = Marvin::Nash.load_file(connections_file) rescue nil
|
101
|
+
if connections.present?
|
102
|
+
# Use epoll if available
|
103
|
+
EventMachine.kqueue
|
104
|
+
EventMachine.epoll
|
105
|
+
EventMachine.run do
|
106
|
+
connections.each_pair do |server, configuration|
|
107
|
+
connect(configuration.merge(:server => server.to_s))
|
108
|
+
end
|
109
|
+
Marvin::Distributed::Server.start if Marvin::Distributed::Handler.registered?
|
110
|
+
@@stopped = false
|
111
|
+
end
|
112
|
+
else
|
113
|
+
logger.fatal "config/connections.yml couldn't be loaded."
|
114
|
+
end
|
129
115
|
end
|
116
|
+
|
117
|
+
def connect(c, &blk)
|
118
|
+
c = normalize_connection_options(c)
|
119
|
+
raise ArgumentError, "Your connection options must specify a server" if !c.server?
|
120
|
+
raise ArgumentError, "Your connection options must specify a port" if !c.port?
|
121
|
+
real_block = blk.present? ? proc { |c| blk.call(connection.client) } : nil
|
122
|
+
logger.info "Connecting to #{c.server}:#{c.port} (using ssl: #{c.ssl?}) - Channels: #{c.channels.join(", ")}"
|
123
|
+
EventMachine.connect(c.server, c.port, EMConnection, c, &real_block)
|
124
|
+
end
|
125
|
+
|
126
|
+
def stop
|
127
|
+
return if @@stopped
|
128
|
+
logger.debug "Telling all connections to quit"
|
129
|
+
connections.dup.each { |connection| connection.quit }
|
130
|
+
logger.debug "Telling Event Machine to Stop"
|
131
|
+
EventMachine.stop_event_loop
|
132
|
+
logger.debug "Stopped."
|
133
|
+
@@stoped = true
|
134
|
+
end
|
135
|
+
|
136
|
+
def add_reconnect(c)
|
137
|
+
logger.warn "Adding timer to reconnect to #{c.server}:#{c.port} in 15 seconds"
|
138
|
+
EventMachine.add_timer(15) do
|
139
|
+
logger.warn "Preparing to reconnect to #{c.server}:#{c.port}"
|
140
|
+
connect(c)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
protected
|
145
|
+
|
146
|
+
def normalize_connection_options(config)
|
147
|
+
config = Marvin::Nash.new(config) if !config.is_a?(Marvin::Nash)
|
148
|
+
config = config.normalized
|
149
|
+
channels = config.channels
|
150
|
+
if channels.present?
|
151
|
+
config.channels = [*channels].compact.reject { |c| c.blank? }
|
152
|
+
else
|
153
|
+
config.channels = []
|
154
|
+
end
|
155
|
+
config.host ||= config.server
|
156
|
+
return config
|
157
|
+
end
|
158
|
+
|
130
159
|
end
|
131
160
|
|
132
161
|
# Registers a callback handle that will be periodically run.
|
133
162
|
def periodically(timing, event_callback)
|
134
|
-
|
135
|
-
EventMachine::add_periodic_timer(timing, &callback)
|
163
|
+
EventMachine.add_periodic_timer(timing) { dispatch(event_callback.to_sym) }
|
136
164
|
end
|
137
165
|
|
138
166
|
end
|
data/lib/marvin/irc/event.rb
CHANGED
@@ -3,32 +3,36 @@ module Marvin::IRC
|
|
3
3
|
attr_accessor :keys, :name, :raw_arguments, :prefix
|
4
4
|
|
5
5
|
def initialize(name, *args)
|
6
|
-
|
7
|
-
|
6
|
+
@name = name.to_sym
|
7
|
+
@keys = args.flatten.map { |k| k.to_sym }
|
8
8
|
end
|
9
9
|
|
10
10
|
def to_hash
|
11
11
|
return @hash_value unless @hash_value.blank?
|
12
12
|
results = {}
|
13
|
-
values =
|
14
|
-
last_index =
|
15
|
-
|
13
|
+
values = @raw_arguments.to_a
|
14
|
+
last_index = @keys.size - 1
|
15
|
+
@keys.each_with_index do |key, i|
|
16
16
|
results[key] = (i == last_index ? values.join(" ").strip : values.shift)
|
17
17
|
end
|
18
|
-
results.merge!(prefix.to_hash) unless prefix.blank?
|
19
|
-
|
18
|
+
results.merge!(@prefix.to_hash) unless @prefix.blank?
|
19
|
+
@hash_value = results
|
20
20
|
end
|
21
21
|
|
22
22
|
def inspect
|
23
|
-
"#<Marvin::IRC::Event name=#{
|
23
|
+
"#<Marvin::IRC::Event name=#{@name} attributes=#{to_hash.inspect} >"
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_event_name(prefix = nil)
|
27
|
+
[prefix, @name].join("_").to_sym
|
24
28
|
end
|
25
29
|
|
26
30
|
def to_incoming_event_name
|
27
|
-
:
|
31
|
+
to_event_name :incoming
|
28
32
|
end
|
29
33
|
|
30
34
|
def to_outgoing_event_name
|
31
|
-
:
|
35
|
+
to_event_name :outgoing
|
32
36
|
end
|
33
37
|
|
34
38
|
end
|
data/lib/marvin/irc.rb
CHANGED
data/lib/marvin/middle_man.rb
CHANGED
@@ -20,16 +20,18 @@ module Marvin
|
|
20
20
|
# attempt to recognize the command and convert
|
21
21
|
# it to an event which can be used for other stuff.
|
22
22
|
def to_event
|
23
|
-
|
23
|
+
# If we have a numeric...
|
24
|
+
if @code =~ /^\d+$/
|
24
25
|
ev = @@commands[:numeric].dup
|
25
26
|
data = @params[0..-2]
|
26
27
|
data << "#{@params.last.include?(" ") ? ":" : ""}#{@params.last}"
|
27
28
|
ev.raw_arguments = [self.code.to_s, data.join(" ")]
|
28
|
-
elsif code == "PRIVMSG" && params.last
|
29
|
-
|
30
|
-
|
29
|
+
elsif code == "PRIVMSG" && params.last =~ /^\001(.*)\001$/
|
30
|
+
results = $1.to_s
|
31
|
+
if results =~ /^ACTION /
|
32
|
+
name, value = :action, results.gsub(/^ACTION /, '')
|
31
33
|
else
|
32
|
-
name, value = :ctcp,
|
34
|
+
name, value = :ctcp, results
|
33
35
|
end
|
34
36
|
self.params[-1] = value
|
35
37
|
ev = @@commands[name].dup
|
@@ -96,9 +98,9 @@ module Marvin
|
|
96
98
|
register_event :ison, :ISON, :nick
|
97
99
|
# Add the default numeric event
|
98
100
|
register_event :numeric, :numeric, :code, :data
|
99
|
-
# And a few others reserved for special
|
100
|
-
register_event :action, :action, :message
|
101
|
-
register_event :ctcp, :ctcp, :message
|
101
|
+
# And a few others reserved for special purposes
|
102
|
+
register_event :action, :action, :target, :message
|
103
|
+
register_event :ctcp, :ctcp, :target, :message
|
102
104
|
|
103
105
|
end
|
104
106
|
end
|
@@ -3,25 +3,30 @@ module Marvin
|
|
3
3
|
module Prefixes
|
4
4
|
# A Generic host mask prefix for a message.
|
5
5
|
class HostMask
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :nick, :user, :host
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def initialize(nick = nil, user = nil, host = nil)
|
9
|
+
@nick = nick || ""
|
10
|
+
@user = user || ""
|
11
|
+
@host = host || ""
|
12
12
|
end
|
13
13
|
|
14
14
|
# Convert it to a usable hash.
|
15
15
|
def to_hash
|
16
|
-
{
|
16
|
+
{
|
17
|
+
:nick => @nick.dup.freeze,
|
18
|
+
:ident => @user.dup.freeze,
|
19
|
+
:host => @host.dup.freeze
|
20
|
+
}
|
17
21
|
end
|
18
22
|
|
19
23
|
# Converts it back to a nicer form / a string.
|
20
24
|
def to_s
|
21
25
|
str = ""
|
22
|
-
str << @
|
26
|
+
str << @nick.to_s
|
23
27
|
str << "!#{@user}" unless @user.blank?
|
24
28
|
str << "@#{@host}" unless @host.blank?
|
29
|
+
str
|
25
30
|
end
|
26
31
|
|
27
32
|
end
|