marvin 0.8.0.0 → 0.8.0.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/bin/marvin +3 -2
- data/lib/marvin.rb +1 -7
- data/lib/marvin/abstract_client.rb +1 -4
- data/lib/marvin/base.rb +4 -2
- data/lib/marvin/command_handler.rb +6 -1
- data/lib/marvin/distributed/client.rb +27 -40
- data/lib/marvin/distributed/handler.rb +0 -1
- data/lib/marvin/distributed/protocol.rb +61 -3
- data/lib/marvin/distributed/server.rb +16 -15
- data/lib/marvin/irc/client.rb +4 -2
- data/lib/marvin/logging_handler.rb +11 -8
- metadata +16 -10
data/bin/marvin
CHANGED
@@ -3,8 +3,9 @@ require 'rubygems'
|
|
3
3
|
require File.join(File.dirname(__FILE__), "..", "lib", "marvin")
|
4
4
|
|
5
5
|
Marvin::Application.processing(ARGV) do |a|
|
6
|
-
|
7
|
-
|
6
|
+
version = Marvin.version
|
7
|
+
version << "p#{Marvin::VERSION[3]}" if Marvin::VERSION[3] != 0
|
8
|
+
a.banner = "Marvin v#{version} - An IRC Library for Ruby"
|
8
9
|
|
9
10
|
a.generator!
|
10
11
|
|
data/lib/marvin.rb
CHANGED
@@ -5,19 +5,14 @@ require 'perennial'
|
|
5
5
|
module Marvin
|
6
6
|
include Perennial
|
7
7
|
|
8
|
-
VERSION = [0, 8, 0,
|
8
|
+
VERSION = [0, 8, 0, 1]
|
9
9
|
|
10
|
-
# Misc.
|
11
|
-
#autoload :Util, 'marvin/util'
|
12
10
|
# Client
|
13
|
-
#autoload :AbstractClient, 'marvin/abstract_client'
|
14
|
-
#autoload :IRC, 'marvin/irc'
|
15
11
|
autoload :TestClient, 'marvin/test_client'
|
16
12
|
# Console of DOOM.
|
17
13
|
autoload :Console, 'marvin/console'
|
18
14
|
# Distributed
|
19
15
|
autoload :Distributed, 'marvin/distributed'
|
20
|
-
autoload :Status, 'marvin/status'
|
21
16
|
# Handler
|
22
17
|
autoload :Base, 'marvin/base'
|
23
18
|
autoload :CommandHandler, 'marvin/command_handler'
|
@@ -25,7 +20,6 @@ module Marvin
|
|
25
20
|
autoload :CoreCommands, 'marvin/core_commands'
|
26
21
|
autoload :MiddleMan, 'marvin/middle_man'
|
27
22
|
# These should be namespaced under IRC
|
28
|
-
#autoload :AbstractParser, 'marvin/abstract_parser'
|
29
23
|
autoload :Parsers, 'marvin/parsers'
|
30
24
|
|
31
25
|
|
data/lib/marvin/base.rb
CHANGED
@@ -76,9 +76,11 @@ module Marvin
|
|
76
76
|
before = dispatcher.handlers
|
77
77
|
register!(dispatcher)
|
78
78
|
after = dispatcher.handlers
|
79
|
-
(after - before).each
|
79
|
+
(after - before).each do |h|
|
80
|
+
h.client = dispatcher
|
81
|
+
h.handle(:reloaded, {})
|
82
|
+
end
|
80
83
|
end
|
81
|
-
|
82
84
|
end
|
83
85
|
|
84
86
|
end
|
@@ -8,7 +8,6 @@ module Marvin
|
|
8
8
|
|
9
9
|
@@exposed_method_mapping = Hash.new { |h,k| h[k] = [] }
|
10
10
|
@@method_descriptions = Hash.new { |h,k| h[k] = {} }
|
11
|
-
@@registered_classes = Set.new
|
12
11
|
|
13
12
|
class << self
|
14
13
|
|
@@ -48,6 +47,12 @@ module Marvin
|
|
48
47
|
"#{command_prefix}#{method}"
|
49
48
|
end
|
50
49
|
|
50
|
+
def reloading!
|
51
|
+
super
|
52
|
+
@@exposed_method_mapping.delete(self)
|
53
|
+
@@method_descriptions.delete(self)
|
54
|
+
end
|
55
|
+
|
51
56
|
end
|
52
57
|
|
53
58
|
on_event :incoming_message, :check_for_commands
|
@@ -26,13 +26,22 @@ module Marvin
|
|
26
26
|
@host_with_port
|
27
27
|
end
|
28
28
|
|
29
|
-
def method_missing(name, *args)
|
29
|
+
def method_missing(name, *args, &blk)
|
30
30
|
logger.debug "Proxying #{name}(#{args.inspect[1..-2]}) to #{@host_with_port}"
|
31
|
+
cb = nil
|
32
|
+
if blk.present?
|
33
|
+
cb = proc do |_, options|
|
34
|
+
if options.is_a?(Hash)
|
35
|
+
value = options.delete("return-value")
|
36
|
+
blk.call(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
31
40
|
@connection.send_message(:action, {
|
32
41
|
"action" => name.to_s,
|
33
42
|
"arguments" => args,
|
34
43
|
"client-host" => @host_with_port
|
35
|
-
})
|
44
|
+
}, &cb)
|
36
45
|
end
|
37
46
|
|
38
47
|
end
|
@@ -43,6 +52,7 @@ module Marvin
|
|
43
52
|
register_handler_method :authentication_failed
|
44
53
|
register_handler_method :authenticated
|
45
54
|
register_handler_method :unauthorized
|
55
|
+
register_handler_method :welcome
|
46
56
|
|
47
57
|
cattr_accessor :stopping
|
48
58
|
self.stopping = false
|
@@ -60,20 +70,13 @@ module Marvin
|
|
60
70
|
def post_init
|
61
71
|
super
|
62
72
|
logger.info "Connected to distributed server"
|
63
|
-
if should_use_tls?
|
64
|
-
logger.info "Attempting to initialize tls"
|
65
|
-
start_tls
|
66
|
-
else
|
67
|
-
process_authentication
|
68
|
-
end
|
69
73
|
end
|
70
74
|
|
71
|
-
def
|
72
|
-
logger.info "
|
73
|
-
process_authentication
|
75
|
+
def post_connect
|
76
|
+
logger.info "Connection started; processing authentication"
|
77
|
+
process_authentication
|
74
78
|
end
|
75
79
|
|
76
|
-
|
77
80
|
def unbind
|
78
81
|
if self.stopping
|
79
82
|
logger.info "Stopping distributed client"
|
@@ -91,6 +94,15 @@ module Marvin
|
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
97
|
+
def handle_welcome(options = {})
|
98
|
+
if should_use_ssl? && !ssl_enabled?
|
99
|
+
request_ssl!
|
100
|
+
else
|
101
|
+
@connected = true
|
102
|
+
post_connect
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
94
106
|
def handle_event(options = {})
|
95
107
|
event = options["event-name"]
|
96
108
|
client_host = options["client-host"]
|
@@ -142,34 +154,9 @@ module Marvin
|
|
142
154
|
end
|
143
155
|
end
|
144
156
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
return {} if blk.blank?
|
149
|
-
cb_id = "callback-#{seld.object_id}-#{Time.now.to_f}"
|
150
|
-
count = 0
|
151
|
-
count += 1 while @callbacks.has_key?(Digest::SHA256.hexdigest("#{cb_id}-#{count}"))
|
152
|
-
final_id = Digest::SHA256.hexdigest("#{cb_id}-#{count}")
|
153
|
-
@callbacks[final_id] = blk
|
154
|
-
{"callback-id" => final_id}
|
155
|
-
end
|
156
|
-
|
157
|
-
def process_callback(hash)
|
158
|
-
if hash.is_a?(Hash) && hash.has_key?("callback-id")
|
159
|
-
callback = @callbacks.delete(hash["callback-id"])
|
160
|
-
callback.call(self, hash)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def host_with_port
|
165
|
-
@host_with_port ||= begin
|
166
|
-
port, ip = Socket.unpack_sockaddr_in(get_peername)
|
167
|
-
"#{ip}:#{port}"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def should_use_tls?
|
172
|
-
@using_tls ||= configuration.encrypted?
|
157
|
+
def request_ssl!
|
158
|
+
logger.info "Requesting SSL for Distributed Client"
|
159
|
+
send_message(:enable_ssl) unless ssl_enabled?
|
173
160
|
end
|
174
161
|
|
175
162
|
end
|
@@ -32,11 +32,19 @@ module Marvin
|
|
32
32
|
send_data "#{payload}\n"
|
33
33
|
end
|
34
34
|
|
35
|
+
def send_message_reply(name, arguments = {})
|
36
|
+
arguments["callback-id"] = @callback_id if @callback_id.present?
|
37
|
+
send_message(name, arguments)
|
38
|
+
end
|
39
|
+
|
35
40
|
def handle_response(response)
|
36
|
-
logger.debug "Handling response in distributed protocol (response
|
41
|
+
logger.debug "Handling response in distributed protocol (response: #{response.inspect})"
|
37
42
|
return unless response.is_a?(Hash) && response.has_key?("message")
|
38
43
|
options = response["options"] || {}
|
44
|
+
@callback_id = response.delete("callback-id")
|
45
|
+
process_callback(options)
|
39
46
|
process_response_message(response["message"], options)
|
47
|
+
@callback_id = nil
|
40
48
|
end
|
41
49
|
|
42
50
|
def host_with_port
|
@@ -46,11 +54,52 @@ module Marvin
|
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
57
|
+
def handle_enable_ssl(opts = {})
|
58
|
+
send_message_reply(:enabled_ssl)
|
59
|
+
enable_ssl
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_enabled_ssl(opts = {})
|
63
|
+
enable_ssl
|
64
|
+
end
|
65
|
+
|
66
|
+
def handle_noop(opts = {})
|
67
|
+
# DO NOTHING.
|
68
|
+
logger.debug "no-op"
|
69
|
+
end
|
70
|
+
|
71
|
+
# After the connection is made and / or ssl is enabled.
|
72
|
+
def post_connect
|
73
|
+
end
|
74
|
+
|
75
|
+
def ssl_handshake_completed
|
76
|
+
logger.debug "SSL Handshake completed"
|
77
|
+
if !connected?
|
78
|
+
@connected = true
|
79
|
+
post_connect
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
49
83
|
protected
|
50
84
|
|
85
|
+
def should_use_ssl?
|
86
|
+
@should_use_ssl ||= configuration.ssl?
|
87
|
+
end
|
88
|
+
|
89
|
+
def ssl_enabled?
|
90
|
+
instance_variable_defined?(:@ssl_enabled) && @ssl_enabled
|
91
|
+
end
|
92
|
+
|
93
|
+
def enable_ssl
|
94
|
+
return if ssl_enabled?
|
95
|
+
logger.debug "Enabling SSL"
|
96
|
+
start_tls
|
97
|
+
@ssl_enabled = true
|
98
|
+
end
|
99
|
+
|
51
100
|
def options_for_callback(blk)
|
52
101
|
return {} if blk.blank?
|
53
|
-
cb_id = "callback-#{
|
102
|
+
cb_id = "callback-#{self.object_id}-#{Time.now.to_f}"
|
54
103
|
count = 0
|
55
104
|
count += 1 while @callbacks.has_key?(Digest::SHA256.hexdigest("#{cb_id}-#{count}"))
|
56
105
|
final_id = Digest::SHA256.hexdigest("#{cb_id}-#{count}")
|
@@ -63,7 +112,7 @@ module Marvin
|
|
63
112
|
@callbacks ||= {}
|
64
113
|
if hash.is_a?(Hash) && hash.has_key?("callback-id")
|
65
114
|
callback = @callbacks.delete(hash["callback-id"])
|
66
|
-
callback.call(self, hash)
|
115
|
+
callback.call(self, hash) if callback.present?
|
67
116
|
end
|
68
117
|
end
|
69
118
|
|
@@ -83,6 +132,15 @@ module Marvin
|
|
83
132
|
self.handler_methods[name] = method
|
84
133
|
end
|
85
134
|
|
135
|
+
# Default Handlers
|
136
|
+
register_handler_method :enable_ssl
|
137
|
+
register_handler_method :enabled_ssl
|
138
|
+
register_handler_method :noop
|
139
|
+
|
140
|
+
def connected?
|
141
|
+
instance_variable_defined?(:@connected) && @connected
|
142
|
+
end
|
143
|
+
|
86
144
|
end
|
87
145
|
end
|
88
146
|
end
|
@@ -16,7 +16,7 @@ module Marvin
|
|
16
16
|
self.free_connections = []
|
17
17
|
self.action_whitelist = [:nick, :pong, :action, :msg, :quit, :part, :join, :command]
|
18
18
|
|
19
|
-
attr_accessor :processing, :configuration
|
19
|
+
attr_accessor :processing, :configuration
|
20
20
|
|
21
21
|
def initialize(*args)
|
22
22
|
@configuration = args.last.is_a?(Marvin::Nash) ? args.pop : Marvin::nash.new
|
@@ -24,18 +24,20 @@ module Marvin
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def post_init
|
27
|
-
super
|
28
27
|
@callbacks = {}
|
29
28
|
logger.info "Got distributed client connection with #{self.host_with_port}"
|
30
|
-
if
|
31
|
-
|
29
|
+
if should_use_ssl?
|
30
|
+
handle_enable_ssl
|
32
31
|
else
|
33
|
-
|
32
|
+
@connected = true
|
33
|
+
post_connect
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
38
|
-
|
37
|
+
def post_connect
|
38
|
+
logger.debug "Remote client available, welcoming"
|
39
|
+
send_message(:welcome)
|
40
|
+
complete_processing
|
39
41
|
end
|
40
42
|
|
41
43
|
def unbind
|
@@ -84,14 +86,17 @@ module Marvin
|
|
84
86
|
def handle_action(options = {})
|
85
87
|
return if fails_auth!
|
86
88
|
logger.debug "Handling action from on #{self.host_with_port}"
|
87
|
-
|
89
|
+
target = lookup_client_for(options["client-host"])
|
88
90
|
action = options["action"]
|
89
91
|
arguments = [*options["arguments"]]
|
90
|
-
return if
|
92
|
+
return if target.blank? || action.blank?
|
91
93
|
begin
|
92
94
|
a = action.to_sym
|
93
|
-
if self.action_whitelist.include?(a)
|
94
|
-
|
95
|
+
if self.action_whitelist.include?(a) && target.respond_to?(a)
|
96
|
+
res = target.send(a, *arguments)
|
97
|
+
if @callback_id.present? && res.respond_to?(:to_json)
|
98
|
+
send_message_reply(:noop, {"return-value" => res.to_json})
|
99
|
+
end
|
95
100
|
else
|
96
101
|
logger.warn "Client attempted invalid action #{a.inspect}"
|
97
102
|
end
|
@@ -123,10 +128,6 @@ module Marvin
|
|
123
128
|
@authenticated ||= false
|
124
129
|
end
|
125
130
|
|
126
|
-
def should_use_tls?
|
127
|
-
@using_tls ||= configuration.encrypted?
|
128
|
-
end
|
129
|
-
|
130
131
|
def fails_auth!
|
131
132
|
if requires_auth?
|
132
133
|
logger.debug "Authentication missing for distributed client"
|
data/lib/marvin/irc/client.rb
CHANGED
@@ -103,8 +103,10 @@ module Marvin::IRC
|
|
103
103
|
EventMachine.kqueue
|
104
104
|
EventMachine.epoll
|
105
105
|
EventMachine.run do
|
106
|
-
connections.
|
107
|
-
|
106
|
+
unless connections.data == false
|
107
|
+
connections.each_pair do |server, configuration|
|
108
|
+
connect(configuration.merge(:server => server.to_s))
|
109
|
+
end
|
108
110
|
end
|
109
111
|
Marvin::Distributed::Server.start if Marvin::Distributed::Handler.registered?
|
110
112
|
@@stopped = false
|
@@ -21,20 +21,23 @@ module Marvin
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
on_event :client_connected
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
24
|
+
on_event :client_connected, :presetup_logging
|
25
|
+
on_event :client_connected, :setup_logging
|
26
|
+
on_event :reloaded, :presetup_logging
|
27
|
+
on_event :reloaded, :setup_logging
|
29
28
|
|
30
|
-
on_event :client_disconnected
|
31
|
-
|
32
|
-
end
|
29
|
+
on_event :client_disconnected, :teardown_logging
|
30
|
+
on_event :reloaded, :teardown_logging
|
33
31
|
|
34
32
|
on_event :outgoing_nick do
|
35
33
|
@nick = options.new_nick
|
36
34
|
end
|
37
35
|
|
36
|
+
def presetup_logging
|
37
|
+
@server = self.client.host_with_port
|
38
|
+
@nick = self.client.nickname
|
39
|
+
end
|
40
|
+
|
38
41
|
# Called when the client connects, over ride it to
|
39
42
|
# do any of your specific setup.
|
40
43
|
def setup_logging
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marvin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0.
|
4
|
+
version: 0.8.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darcy Laycock
|
@@ -10,27 +10,27 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
|
12
12
|
date: 2009-09-25 00:00:00 +08:00
|
13
|
-
default_executable:
|
13
|
+
default_executable: marvin
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: perennial
|
17
17
|
type: :runtime
|
18
18
|
version_requirement:
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.
|
23
|
+
version: 1.0.0.0
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name: eventmachine
|
26
|
+
name: eventmachine
|
27
27
|
type: :runtime
|
28
28
|
version_requirement:
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.12.
|
33
|
+
version: 0.12.8
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: json
|
@@ -42,10 +42,16 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: "0"
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: |-
|
46
|
+
Marvin is a library (also usable in framework / application form) that
|
47
|
+
makes it simple and fast to build applications around IRC. With an emphasis
|
48
|
+
on making common tasks (e.g. replies, bots using method call style syntax
|
49
|
+
and the like) easy, whilst still making it possible to do more complex thing
|
50
|
+
(1 connection, N worker processes, Multiple servers, etc) it aims to make
|
51
|
+
working with IRC in an evented fashion fun and easy for all rubyists.
|
46
52
|
email: sutto@sutto.net
|
47
|
-
executables:
|
48
|
-
|
53
|
+
executables:
|
54
|
+
- marvin
|
49
55
|
extensions: []
|
50
56
|
|
51
57
|
extra_rdoc_files: []
|
@@ -131,6 +137,6 @@ rubyforge_project:
|
|
131
137
|
rubygems_version: 1.3.2
|
132
138
|
signing_key:
|
133
139
|
specification_version: 3
|
134
|
-
summary: Evented IRC Library
|
140
|
+
summary: Evented IRC Library for Ruby, built on EventMachine and Perennial.
|
135
141
|
test_files: []
|
136
142
|
|